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