079dac2372a932200b6ffdc41320691a75129c92
[WebKit-https.git] / Source / WebCore / platform / MemoryPressureHandler.h
1 /*
2  * Copyright (C) 2011 Apple Inc. All Rights Reserved.
3  * Copyright (C) 2014 Raspberry Pi Foundation. All Rights Reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #ifndef MemoryPressureHandler_h
28 #define MemoryPressureHandler_h
29
30 #include <atomic>
31 #include <ctime>
32 #include <functional>
33 #include <wtf/FastMalloc.h>
34 #include <wtf/Forward.h>
35
36 #if PLATFORM(IOS)
37 #include <wtf/ThreadingPrimitives.h>
38 #elif OS(LINUX)
39 #include "Timer.h"
40 #endif
41
42 namespace WebCore {
43
44 #if PLATFORM(IOS)
45 enum MemoryPressureReason {
46     MemoryPressureReasonNone = 0 << 0,
47     MemoryPressureReasonVMPressure = 1 << 0,
48     MemoryPressureReasonVMStatus = 1 << 1,
49 };
50 #endif
51
52 enum class Critical { No, Yes };
53 enum class Synchronous { No, Yes };
54
55 typedef std::function<void(Critical, Synchronous)> LowMemoryHandler;
56
57 class MemoryPressureHandler {
58     WTF_MAKE_FAST_ALLOCATED;
59     friend class WTF::NeverDestroyed<MemoryPressureHandler>;
60 public:
61     WEBCORE_EXPORT static MemoryPressureHandler& singleton();
62
63     WEBCORE_EXPORT void install();
64
65     void setLowMemoryHandler(LowMemoryHandler handler)
66     {
67         ASSERT(!m_installed);
68         m_lowMemoryHandler = handler;
69     }
70
71     bool isUnderMemoryPressure() const { return m_underMemoryPressure; }
72     void setUnderMemoryPressure(bool b) { m_underMemoryPressure = b; }
73
74 #if PLATFORM(IOS)
75     // FIXME: Can we share more of this with OpenSource?
76     WEBCORE_EXPORT void installMemoryReleaseBlock(void (^releaseMemoryBlock)(), bool clearPressureOnMemoryRelease = true);
77     WEBCORE_EXPORT void setReceivedMemoryPressure(MemoryPressureReason);
78     WEBCORE_EXPORT void clearMemoryPressure();
79     WEBCORE_EXPORT bool shouldWaitForMemoryClearMessage();
80     void respondToMemoryPressureIfNeeded();
81 #elif OS(LINUX)
82     static void waitForMemoryPressureEvent(void*);
83 #endif
84
85     class ReliefLogger {
86     public:
87         explicit ReliefLogger(const char *log)
88             : m_logString(log)
89             , m_initialMemory(s_loggingEnabled ? platformMemoryUsage() : 0)
90         {
91         }
92
93         ~ReliefLogger()
94         {
95             if (s_loggingEnabled)
96                 platformLog();
97         }
98
99         const char* logString() const { return m_logString; }
100         static void setLoggingEnabled(bool enabled) { s_loggingEnabled = enabled; }
101         static bool loggingEnabled() { return s_loggingEnabled; }
102
103     private:
104         size_t platformMemoryUsage();
105         void platformLog();
106
107         const char* m_logString;
108         size_t m_initialMemory;
109
110         WEBCORE_EXPORT static bool s_loggingEnabled;
111     };
112
113     WEBCORE_EXPORT void releaseMemory(Critical, Synchronous = Synchronous::No);
114
115 private:
116     void releaseNoncriticalMemory();
117     void releaseCriticalMemory(Synchronous);
118
119     void uninstall();
120
121     void holdOff(unsigned);
122
123     MemoryPressureHandler();
124     ~MemoryPressureHandler() = delete;
125
126     void respondToMemoryPressure(Critical, Synchronous = Synchronous::No);
127     void platformReleaseMemory(Critical);
128
129     bool m_installed;
130     time_t m_lastRespondTime;
131     LowMemoryHandler m_lowMemoryHandler;
132
133     std::atomic<bool> m_underMemoryPressure;
134
135 #if PLATFORM(IOS)
136     uint32_t m_memoryPressureReason;
137     bool m_clearPressureOnMemoryRelease;
138     void (^m_releaseMemoryBlock)();
139     CFRunLoopObserverRef m_observer;
140     DeprecatedMutex m_observerMutex;
141 #elif OS(LINUX)
142     int m_eventFD;
143     int m_pressureLevelFD;
144     WTF::ThreadIdentifier m_threadID;
145     Timer m_holdOffTimer;
146     void holdOffTimerFired();
147     void logErrorAndCloseFDs(const char* error);
148 #endif
149 };
150
151 } // namespace WebCore
152
153 #endif // MemoryPressureHandler_h