b9c8cec3541c384c4bed03f389f167f73c9e2555
[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 typedef std::function<void(bool critical)> LowMemoryHandler;
53
54 class MemoryPressureHandler {
55     WTF_MAKE_FAST_ALLOCATED;
56     friend class WTF::NeverDestroyed<MemoryPressureHandler>;
57 public:
58     WEBCORE_EXPORT static MemoryPressureHandler& singleton();
59
60     WEBCORE_EXPORT void install();
61
62     void setLowMemoryHandler(LowMemoryHandler handler)
63     {
64         ASSERT(!m_installed);
65         m_lowMemoryHandler = handler;
66     }
67
68     bool isUnderMemoryPressure() const { return m_underMemoryPressure; }
69     void setUnderMemoryPressure(bool b) { m_underMemoryPressure = b; }
70
71 #if PLATFORM(IOS)
72     // FIXME: Can we share more of this with OpenSource?
73     WEBCORE_EXPORT void installMemoryReleaseBlock(void (^releaseMemoryBlock)(), bool clearPressureOnMemoryRelease = true);
74     WEBCORE_EXPORT void setReceivedMemoryPressure(MemoryPressureReason);
75     WEBCORE_EXPORT void clearMemoryPressure();
76     WEBCORE_EXPORT bool shouldWaitForMemoryClearMessage();
77     void respondToMemoryPressureIfNeeded();
78 #elif OS(LINUX)
79     static void waitForMemoryPressureEvent(void*);
80 #endif
81
82     class ReliefLogger {
83     public:
84         explicit ReliefLogger(const char *log)
85             : m_logString(log)
86             , m_initialMemory(s_loggingEnabled ? platformMemoryUsage() : 0)
87         {
88         }
89
90         ~ReliefLogger()
91         {
92             if (s_loggingEnabled)
93                 platformLog();
94         }
95
96         const char* logString() const { return m_logString; }
97         static void setLoggingEnabled(bool enabled) { s_loggingEnabled = enabled; }
98         static bool loggingEnabled() { return s_loggingEnabled; }
99
100     private:
101         size_t platformMemoryUsage();
102         void platformLog();
103
104         const char* m_logString;
105         size_t m_initialMemory;
106
107         WEBCORE_EXPORT static bool s_loggingEnabled;
108     };
109
110     WEBCORE_EXPORT void releaseMemory(bool critical);
111
112 private:
113     void releaseNoncriticalMemory();
114     void releaseCriticalMemory();
115
116     void uninstall();
117
118     void holdOff(unsigned);
119
120     MemoryPressureHandler();
121     ~MemoryPressureHandler() = delete;
122
123     void respondToMemoryPressure(bool critical);
124     void platformReleaseMemory(bool critical);
125
126     bool m_installed;
127     time_t m_lastRespondTime;
128     LowMemoryHandler m_lowMemoryHandler;
129
130     std::atomic<bool> m_underMemoryPressure;
131
132 #if PLATFORM(IOS)
133     uint32_t m_memoryPressureReason;
134     bool m_clearPressureOnMemoryRelease;
135     void (^m_releaseMemoryBlock)();
136     CFRunLoopObserverRef m_observer;
137     Mutex m_observerMutex;
138 #elif OS(LINUX)
139     int m_eventFD;
140     int m_pressureLevelFD;
141     WTF::ThreadIdentifier m_threadID;
142     Timer m_holdOffTimer;
143     void holdOffTimerFired();
144     void logErrorAndCloseFDs(const char* error);
145 #endif
146 };
147
148 } // namespace WebCore
149
150 #endif // MemoryPressureHandler_h