1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsMemoryImpl.h"
8 #include "nsThreadUtils.h"
10 #include "nsIObserver.h"
11 #include "nsIObserverService.h"
12 #include "nsISimpleEnumerator.h"
15 #include "mozilla/Services.h"
20 // Minimum memory threshold for a device to be considered
21 // a low memory platform. This value has be in sync with
22 // Java's equivalent threshold, defined in
23 // mobile/android/base/util/HardwareUtils.java
24 #define LOW_MEMORY_THRESHOLD_KB (384 * 1024)
27 static nsMemoryImpl sGlobalMemory
;
29 NS_IMPL_QUERY_INTERFACE(nsMemoryImpl
, nsIMemory
)
32 nsMemoryImpl::Alloc(size_t aSize
)
34 return NS_Alloc(aSize
);
38 nsMemoryImpl::Realloc(void* aPtr
, size_t aSize
)
40 return NS_Realloc(aPtr
, aSize
);
44 nsMemoryImpl::Free(void* aPtr
)
50 nsMemoryImpl::HeapMinimize(bool aImmediate
)
52 return FlushMemory(MOZ_UTF16("heap-minimize"), aImmediate
);
56 nsMemoryImpl::IsLowMemory(bool* aResult
)
58 NS_ERROR("IsLowMemory is deprecated. See bug 592308.");
64 nsMemoryImpl::IsLowMemoryPlatform(bool* aResult
)
67 static int sLowMemory
= -1; // initialize to unknown, lazily evaluate to 0 or 1
68 if (sLowMemory
== -1) {
69 sLowMemory
= 0; // assume "not low memory" in case file operations fail
72 // check if MemTotal from /proc/meminfo is less than LOW_MEMORY_THRESHOLD_KB
73 FILE* fd
= fopen("/proc/meminfo", "r");
78 int rv
= fscanf(fd
, "MemTotal: %llu kB", &mem
);
85 sLowMemory
= (mem
< LOW_MEMORY_THRESHOLD_KB
) ? 1 : 0;
87 *aResult
= (sLowMemory
== 1);
95 nsMemoryImpl::Create(nsISupports
* aOuter
, const nsIID
& aIID
, void** aResult
)
97 if (NS_WARN_IF(aOuter
)) {
98 return NS_ERROR_NO_AGGREGATION
;
100 return sGlobalMemory
.QueryInterface(aIID
, aResult
);
104 nsMemoryImpl::FlushMemory(const char16_t
* aReason
, bool aImmediate
)
109 // They've asked us to run the flusher *immediately*. We've
110 // got to be on the UI main thread for us to be able to do
112 if (!NS_IsMainThread()) {
113 NS_ERROR("can't synchronously flush memory: not on UI thread");
114 return NS_ERROR_FAILURE
;
118 bool lastVal
= sIsFlushing
.exchange(true);
123 PRIntervalTime now
= PR_IntervalNow();
125 // Run the flushers immediately if we can; otherwise, proxy to the
126 // UI thread an run 'em asynchronously.
128 rv
= RunFlushers(aReason
);
130 // Don't broadcast more than once every 1000ms to avoid being noisy
131 if (PR_IntervalToMicroseconds(now
- sLastFlushTime
) > 1000) {
132 sFlushEvent
.mReason
= aReason
;
133 rv
= NS_DispatchToMainThread(&sFlushEvent
);
137 sLastFlushTime
= now
;
142 nsMemoryImpl::RunFlushers(const char16_t
* aReason
)
144 nsCOMPtr
<nsIObserverService
> os
= mozilla::services::GetObserverService();
148 // os->NotifyObservers(this, "memory-pressure", aReason);
149 // we are going to do this manually to see who/what is
152 nsCOMPtr
<nsISimpleEnumerator
> e
;
153 os
->EnumerateObservers("memory-pressure", getter_AddRefs(e
));
156 nsCOMPtr
<nsIObserver
> observer
;
159 while (NS_SUCCEEDED(e
->HasMoreElements(&loop
)) && loop
) {
160 nsCOMPtr
<nsISupports
> supports
;
161 e
->GetNext(getter_AddRefs(supports
));
167 observer
= do_QueryInterface(supports
);
168 observer
->Observe(observer
, "memory-pressure", aReason
);
177 // XXX need NS_IMPL_STATIC_ADDREF/RELEASE
178 NS_IMETHODIMP_(MozExternalRefCountType
)
179 nsMemoryImpl::FlushEvent::AddRef()
183 NS_IMETHODIMP_(MozExternalRefCountType
)
184 nsMemoryImpl::FlushEvent::Release()
188 NS_IMPL_QUERY_INTERFACE(nsMemoryImpl::FlushEvent
, nsIRunnable
)
191 nsMemoryImpl::FlushEvent::Run()
193 sGlobalMemory
.RunFlushers(mReason
);
197 mozilla::Atomic
<bool>
198 nsMemoryImpl::sIsFlushing
;
201 nsMemoryImpl::sLastFlushTime
= 0;
203 nsMemoryImpl::FlushEvent
204 nsMemoryImpl::sFlushEvent
;
207 NS_Alloc(size_t aSize
)
209 return moz_xmalloc(aSize
);
213 NS_Realloc(void* aPtr
, size_t aSize
)
215 return moz_xrealloc(aPtr
, aSize
);
225 NS_GetMemoryManager(nsIMemory
** aResult
)
227 return sGlobalMemory
.QueryInterface(NS_GET_IID(nsIMemory
), (void**)aResult
);