/* * Copyright (C) 2011 Apple Inc. All Rights Reserved. * Copyright (C) 2014 Raspberry Pi Foundation. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef MemoryPressureHandler_h #define MemoryPressureHandler_h #include #include #include #include #include #if PLATFORM(IOS) #include #include #elif OS(LINUX) #include "Timer.h" #endif namespace WebCore { #if PLATFORM(IOS) enum MemoryPressureReason { MemoryPressureReasonNone = 0 << 0, MemoryPressureReasonVMPressure = 1 << 0, MemoryPressureReasonVMStatus = 1 << 1, }; #endif enum class Critical { No, Yes }; enum class Synchronous { No, Yes }; typedef std::function LowMemoryHandler; class MemoryPressureHandler { WTF_MAKE_FAST_ALLOCATED; friend class WTF::NeverDestroyed; public: WEBCORE_EXPORT static MemoryPressureHandler& singleton(); WEBCORE_EXPORT void install(); void setLowMemoryHandler(LowMemoryHandler handler) { ASSERT(!m_installed); m_lowMemoryHandler = handler; } bool isUnderMemoryPressure() const { return m_underMemoryPressure; } void setUnderMemoryPressure(bool b) { m_underMemoryPressure = b; } #if PLATFORM(IOS) // FIXME: Can we share more of this with OpenSource? WEBCORE_EXPORT void installMemoryReleaseBlock(void (^releaseMemoryBlock)(), bool clearPressureOnMemoryRelease = true); WEBCORE_EXPORT void setReceivedMemoryPressure(MemoryPressureReason); WEBCORE_EXPORT void clearMemoryPressure(); WEBCORE_EXPORT bool shouldWaitForMemoryClearMessage(); void respondToMemoryPressureIfNeeded(); #elif OS(LINUX) static void waitForMemoryPressureEvent(void*); #endif class ReliefLogger { public: explicit ReliefLogger(const char *log) : m_logString(log) , m_initialMemory(s_loggingEnabled ? platformMemoryUsage() : 0) { } ~ReliefLogger() { if (s_loggingEnabled) platformLog(); } const char* logString() const { return m_logString; } static void setLoggingEnabled(bool enabled) { s_loggingEnabled = enabled; } static bool loggingEnabled() { return s_loggingEnabled; } private: size_t platformMemoryUsage(); void platformLog(); const char* m_logString; size_t m_initialMemory; WEBCORE_EXPORT static bool s_loggingEnabled; }; WEBCORE_EXPORT void releaseMemory(Critical, Synchronous = Synchronous::No); private: void releaseNoncriticalMemory(); void releaseCriticalMemory(Synchronous); void uninstall(); void holdOff(unsigned); MemoryPressureHandler(); ~MemoryPressureHandler() = delete; void respondToMemoryPressure(Critical, Synchronous = Synchronous::No); void platformReleaseMemory(Critical); bool m_installed; time_t m_lastRespondTime; LowMemoryHandler m_lowMemoryHandler; std::atomic m_underMemoryPressure; #if PLATFORM(IOS) uint32_t m_memoryPressureReason; bool m_clearPressureOnMemoryRelease; void (^m_releaseMemoryBlock)(); CFRunLoopObserverRef m_observer; Lock m_observerMutex; #elif OS(LINUX) int m_eventFD; int m_pressureLevelFD; WTF::ThreadIdentifier m_threadID; Timer m_holdOffTimer; void holdOffTimerFired(); void logErrorAndCloseFDs(const char* error); #endif }; } // namespace WebCore #endif // MemoryPressureHandler_h