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