xpcom/base/nsMemoryImpl.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #include "nsMemoryImpl.h"
     7 #include "nsThreadUtils.h"
     9 #include "nsIObserver.h"
    10 #include "nsIObserverService.h"
    11 #include "nsISimpleEnumerator.h"
    13 #include "nsCOMPtr.h"
    14 #include "mozilla/Services.h"
    16 #ifdef ANDROID
    17 #include <stdio.h>
    19 // Minimum memory threshold for a device to be considered
    20 // a low memory platform. This value has be in sync with
    21 // Java's equivalent threshold, defined in
    22 // mobile/android/base/util/HardwareUtils.java
    23 #define LOW_MEMORY_THRESHOLD_KB (384 * 1024)
    24 #endif
    26 static nsMemoryImpl sGlobalMemory;
    28 NS_IMPL_QUERY_INTERFACE(nsMemoryImpl, nsIMemory)
    30 NS_IMETHODIMP_(void*)
    31 nsMemoryImpl::Alloc(size_t size)
    32 {
    33     return NS_Alloc(size);
    34 }
    36 NS_IMETHODIMP_(void*)
    37 nsMemoryImpl::Realloc(void* ptr, size_t size)
    38 {
    39     return NS_Realloc(ptr, size);
    40 }
    42 NS_IMETHODIMP_(void)
    43 nsMemoryImpl::Free(void* ptr)
    44 {
    45     NS_Free(ptr);
    46 }
    48 NS_IMETHODIMP
    49 nsMemoryImpl::HeapMinimize(bool aImmediate)
    50 {
    51     return FlushMemory(MOZ_UTF16("heap-minimize"), aImmediate);
    52 }
    54 NS_IMETHODIMP
    55 nsMemoryImpl::IsLowMemory(bool *result)
    56 {
    57     NS_ERROR("IsLowMemory is deprecated.  See bug 592308.");
    58     *result = false;
    59     return NS_OK;
    60 }
    62 NS_IMETHODIMP
    63 nsMemoryImpl::IsLowMemoryPlatform(bool *result)
    64 {
    65 #ifdef ANDROID
    66     static int sLowMemory = -1; // initialize to unknown, lazily evaluate to 0 or 1
    67     if (sLowMemory == -1) {
    68         sLowMemory = 0; // assume "not low memory" in case file operations fail
    69         *result = false;
    71         // check if MemTotal from /proc/meminfo is less than LOW_MEMORY_THRESHOLD_KB
    72         FILE* fd = fopen("/proc/meminfo", "r");
    73         if (!fd) {
    74             return NS_OK;
    75         }
    76         uint64_t mem = 0;
    77         int rv = fscanf(fd, "MemTotal: %llu kB", &mem);
    78         if (fclose(fd)) {
    79             return NS_OK;
    80         }
    81         if (rv != 1) {
    82             return NS_OK;
    83         }
    84         sLowMemory = (mem < LOW_MEMORY_THRESHOLD_KB) ? 1 : 0;
    85     }
    86     *result = (sLowMemory == 1);
    87 #else
    88     *result = false;
    89 #endif
    90     return NS_OK;
    91 }
    93 /*static*/ nsresult
    94 nsMemoryImpl::Create(nsISupports* outer, const nsIID& aIID, void **aResult)
    95 {
    96     if (NS_WARN_IF(outer))
    97         return NS_ERROR_NO_AGGREGATION;
    98     return sGlobalMemory.QueryInterface(aIID, aResult);
    99 }
   101 nsresult
   102 nsMemoryImpl::FlushMemory(const char16_t* aReason, bool aImmediate)
   103 {
   104     nsresult rv = NS_OK;
   106     if (aImmediate) {
   107         // They've asked us to run the flusher *immediately*. We've
   108         // got to be on the UI main thread for us to be able to do
   109         // that...are we?
   110         if (!NS_IsMainThread()) {
   111             NS_ERROR("can't synchronously flush memory: not on UI thread");
   112             return NS_ERROR_FAILURE;
   113         }
   114     }
   116     bool lastVal = sIsFlushing.exchange(true);
   117     if (lastVal)
   118         return NS_OK;
   120     PRIntervalTime now = PR_IntervalNow();
   122     // Run the flushers immediately if we can; otherwise, proxy to the
   123     // UI thread an run 'em asynchronously.
   124     if (aImmediate) {
   125         rv = RunFlushers(aReason);
   126     }
   127     else {
   128         // Don't broadcast more than once every 1000ms to avoid being noisy
   129         if (PR_IntervalToMicroseconds(now - sLastFlushTime) > 1000) {
   130             sFlushEvent.mReason = aReason;
   131             rv = NS_DispatchToMainThread(&sFlushEvent, NS_DISPATCH_NORMAL);
   132         }
   133     }
   135     sLastFlushTime = now;
   136     return rv;
   137 }
   139 nsresult
   140 nsMemoryImpl::RunFlushers(const char16_t* aReason)
   141 {
   142     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
   143     if (os) {
   145         // Instead of:
   146         //  os->NotifyObservers(this, "memory-pressure", aReason);
   147         // we are going to do this manually to see who/what is
   148         // deallocating.
   150         nsCOMPtr<nsISimpleEnumerator> e;
   151         os->EnumerateObservers("memory-pressure", getter_AddRefs(e));
   153         if ( e ) {
   154           nsCOMPtr<nsIObserver> observer;
   155           bool loop = true;
   157           while (NS_SUCCEEDED(e->HasMoreElements(&loop)) && loop)
   158           {
   159               nsCOMPtr<nsISupports> supports;
   160               e->GetNext(getter_AddRefs(supports));
   162               if (!supports)
   163                   continue;
   165               observer = do_QueryInterface(supports);
   166               observer->Observe(observer, "memory-pressure", aReason);
   167           }
   168         }
   169     }
   171     sIsFlushing = false;
   172     return NS_OK;
   173 }
   175 // XXX need NS_IMPL_STATIC_ADDREF/RELEASE
   176 NS_IMETHODIMP_(MozExternalRefCountType) nsMemoryImpl::FlushEvent::AddRef() { return 2; }
   177 NS_IMETHODIMP_(MozExternalRefCountType) nsMemoryImpl::FlushEvent::Release() { return 1; }
   178 NS_IMPL_QUERY_INTERFACE(nsMemoryImpl::FlushEvent, nsIRunnable)
   180 NS_IMETHODIMP
   181 nsMemoryImpl::FlushEvent::Run()
   182 {
   183     sGlobalMemory.RunFlushers(mReason);
   184     return NS_OK;
   185 }
   187 mozilla::Atomic<bool>
   188 nsMemoryImpl::sIsFlushing;
   190 PRIntervalTime
   191 nsMemoryImpl::sLastFlushTime = 0;
   193 nsMemoryImpl::FlushEvent
   194 nsMemoryImpl::sFlushEvent;
   196 XPCOM_API(void*)
   197 NS_Alloc(size_t size)
   198 {
   199     return moz_xmalloc(size);
   200 }
   202 XPCOM_API(void*)
   203 NS_Realloc(void* ptr, size_t size)
   204 {
   205     return moz_xrealloc(ptr, size);
   206 }
   208 XPCOM_API(void)
   209 NS_Free(void* ptr)
   210 {
   211     moz_free(ptr);
   212 }
   214 nsresult
   215 NS_GetMemoryManager(nsIMemory* *result)
   216 {
   217     return sGlobalMemory.QueryInterface(NS_GET_IID(nsIMemory), (void**) result);
   218 }

mercurial