<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[177216] trunk/Source/WebCore</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/177216">177216</a></dd>
<dt>Author</dt> <dd>changseok.oh@collabora.com</dd>
<dt>Date</dt> <dd>2014-12-12 01:21:15 -0800 (Fri, 12 Dec 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Implement MemoryPressureHandler for Linux system
https://bugs.webkit.org/show_bug.cgi?id=123532

Reviewed by Sergio Villar Senin.

This is an initial implementation to support MemoryPressureHandler for linux system.
The patch is based on Tomeu's last patch and improved on top of it.
Most of current linux distributions support cgroup, so that we use the memory.pressure_level
mechanism of cgroup to get notifications when an application reaches the 'low' memory
pressure level.

No new tests since no engine behavior changed.

* PlatformEfl.cmake:
* PlatformGTK.cmake:
* platform/MemoryPressureHandler.cpp:
(WebCore::MemoryPressureHandler::MemoryPressureHandler):
* platform/MemoryPressureHandler.h:
* platform/linux/MemoryPressureHandlerLinux.cpp: Added.
(WebCore::nextToken):
(WebCore::MemoryPressureHandler::~MemoryPressureHandler):
(WebCore::MemoryPressureHandler::waitForMemoryPressureEvent): run in a seperated thread
to listen 'low' level event.
(WebCore::MemoryPressureHandler::logErrorAndCloseFDs):
(WebCore::MemoryPressureHandler::install):
(WebCore::MemoryPressureHandler::uninstall):
(WebCore::MemoryPressureHandler::holdOffTimerFired):
(WebCore::MemoryPressureHandler::holdOff):
(WebCore::MemoryPressureHandler::respondToMemoryPressure):
(WebCore::MemoryPressureHandler::platformReleaseMemory):
(WebCore::MemoryPressureHandler::ReliefLogger::platformLog):
(WebCore::MemoryPressureHandler::ReliefLogger::platformMemoryUsage): read /proc/self/status
to get VM amount used by current process.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorePlatformEflcmake">trunk/Source/WebCore/PlatformEfl.cmake</a></li>
<li><a href="#trunkSourceWebCorePlatformGTKcmake">trunk/Source/WebCore/PlatformGTK.cmake</a></li>
<li><a href="#trunkSourceWebCoreplatformMemoryPressureHandlercpp">trunk/Source/WebCore/platform/MemoryPressureHandler.cpp</a></li>
<li><a href="#trunkSourceWebCoreplatformMemoryPressureHandlerh">trunk/Source/WebCore/platform/MemoryPressureHandler.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreplatformlinuxMemoryPressureHandlerLinuxcpp">trunk/Source/WebCore/platform/linux/MemoryPressureHandlerLinux.cpp</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (177215 => 177216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2014-12-12 09:17:21 UTC (rev 177215)
+++ trunk/Source/WebCore/ChangeLog        2014-12-12 09:21:15 UTC (rev 177216)
</span><span class="lines">@@ -1,3 +1,39 @@
</span><ins>+2014-12-12  ChangSeok Oh  &lt;changseok.oh@collabora.com&gt;
+
+        Implement MemoryPressureHandler for Linux system
+        https://bugs.webkit.org/show_bug.cgi?id=123532
+
+        Reviewed by Sergio Villar Senin.
+
+        This is an initial implementation to support MemoryPressureHandler for linux system.
+        The patch is based on Tomeu's last patch and improved on top of it.
+        Most of current linux distributions support cgroup, so that we use the memory.pressure_level
+        mechanism of cgroup to get notifications when an application reaches the 'low' memory
+        pressure level.
+
+        No new tests since no engine behavior changed.
+
+        * PlatformEfl.cmake:
+        * PlatformGTK.cmake:
+        * platform/MemoryPressureHandler.cpp:
+        (WebCore::MemoryPressureHandler::MemoryPressureHandler):
+        * platform/MemoryPressureHandler.h:
+        * platform/linux/MemoryPressureHandlerLinux.cpp: Added.
+        (WebCore::nextToken):
+        (WebCore::MemoryPressureHandler::~MemoryPressureHandler):
+        (WebCore::MemoryPressureHandler::waitForMemoryPressureEvent): run in a seperated thread
+        to listen 'low' level event.
+        (WebCore::MemoryPressureHandler::logErrorAndCloseFDs):
+        (WebCore::MemoryPressureHandler::install):
+        (WebCore::MemoryPressureHandler::uninstall):
+        (WebCore::MemoryPressureHandler::holdOffTimerFired):
+        (WebCore::MemoryPressureHandler::holdOff):
+        (WebCore::MemoryPressureHandler::respondToMemoryPressure):
+        (WebCore::MemoryPressureHandler::platformReleaseMemory):
+        (WebCore::MemoryPressureHandler::ReliefLogger::platformLog):
+        (WebCore::MemoryPressureHandler::ReliefLogger::platformMemoryUsage): read /proc/self/status
+        to get VM amount used by current process.
+
</ins><span class="cx"> 2014-12-12  Simon Fraser  &lt;simon.fraser@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Layer borders on contentsLayers don't correctly toggle with the rest of the borders
</span></span></pre></div>
<a id="trunkSourceWebCorePlatformEflcmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/PlatformEfl.cmake (177215 => 177216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/PlatformEfl.cmake        2014-12-12 09:17:21 UTC (rev 177215)
+++ trunk/Source/WebCore/PlatformEfl.cmake        2014-12-12 09:21:15 UTC (rev 177216)
</span><span class="lines">@@ -212,6 +212,7 @@
</span><span class="cx">     platform/image-decoders/webp/WEBPImageDecoder.cpp
</span><span class="cx"> 
</span><span class="cx">     platform/linux/GamepadDeviceLinux.cpp
</span><ins>+    platform/linux/MemoryPressureHandlerLinux.cpp
</ins><span class="cx"> 
</span><span class="cx">     platform/mediastream/gstreamer/MediaStreamCenterGStreamer.cpp
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCorePlatformGTKcmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/PlatformGTK.cmake (177215 => 177216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/PlatformGTK.cmake        2014-12-12 09:17:21 UTC (rev 177215)
+++ trunk/Source/WebCore/PlatformGTK.cmake        2014-12-12 09:21:15 UTC (rev 177216)
</span><span class="lines">@@ -156,6 +156,7 @@
</span><span class="cx">     platform/image-decoders/webp/WEBPImageDecoder.cpp
</span><span class="cx"> 
</span><span class="cx">     platform/linux/GamepadDeviceLinux.cpp
</span><ins>+    platform/linux/MemoryPressureHandlerLinux.cpp
</ins><span class="cx"> 
</span><span class="cx">     platform/mediastream/gstreamer/MediaStreamCenterGStreamer.cpp
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformMemoryPressureHandlercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/MemoryPressureHandler.cpp (177215 => 177216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/MemoryPressureHandler.cpp        2014-12-12 09:17:21 UTC (rev 177215)
+++ trunk/Source/WebCore/platform/MemoryPressureHandler.cpp        2014-12-12 09:21:15 UTC (rev 177216)
</span><span class="lines">@@ -64,6 +64,11 @@
</span><span class="cx">     , m_clearPressureOnMemoryRelease(true)
</span><span class="cx">     , m_releaseMemoryBlock(0)
</span><span class="cx">     , m_observer(0)
</span><ins>+#elif OS(LINUX)
+    , m_eventFD(0)
+    , m_pressureLevelFD(0)
+    , m_threadID(0)
+    , m_holdOffTimer(*this, &amp;MemoryPressureHandler::holdOffTimerFired)
</ins><span class="cx"> #endif
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="lines">@@ -143,7 +148,7 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-#if !PLATFORM(COCOA)
</del><ins>+#if !PLATFORM(COCOA) &amp;&amp; !OS(LINUX)
</ins><span class="cx"> void MemoryPressureHandler::install() { }
</span><span class="cx"> void MemoryPressureHandler::uninstall() { }
</span><span class="cx"> void MemoryPressureHandler::holdOff(unsigned) { }
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformMemoryPressureHandlerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/MemoryPressureHandler.h (177215 => 177216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/MemoryPressureHandler.h        2014-12-12 09:17:21 UTC (rev 177215)
+++ trunk/Source/WebCore/platform/MemoryPressureHandler.h        2014-12-12 09:21:15 UTC (rev 177216)
</span><span class="lines">@@ -1,5 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2011 Apple Inc. All Rights Reserved.
</span><ins>+ * Copyright (C) 2014 Raspberry Pi Foundation. All Rights Reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -32,6 +33,8 @@
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(IOS)
</span><span class="cx"> #include &lt;wtf/ThreadingPrimitives.h&gt;
</span><ins>+#elif OS(LINUX)
+#include &quot;Timer.h&quot;
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx"> namespace WebCore {
</span><span class="lines">@@ -69,6 +72,8 @@
</span><span class="cx">     WEBCORE_EXPORT void clearMemoryPressure();
</span><span class="cx">     WEBCORE_EXPORT bool shouldWaitForMemoryClearMessage();
</span><span class="cx">     void respondToMemoryPressureIfNeeded();
</span><ins>+#elif OS(LINUX)
+    static void waitForMemoryPressureEvent(void*);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     class ReliefLogger {
</span><span class="lines">@@ -127,9 +132,16 @@
</span><span class="cx">     void (^m_releaseMemoryBlock)();
</span><span class="cx">     CFRunLoopObserverRef m_observer;
</span><span class="cx">     Mutex m_observerMutex;
</span><ins>+#elif OS(LINUX)
+    int m_eventFD;
+    int m_pressureLevelFD;
+    WTF::ThreadIdentifier m_threadID;
+    Timer m_holdOffTimer;
+    void holdOffTimerFired();
+    void logErrorAndCloseFDs(const char* error);
</ins><span class="cx"> #endif
</span><span class="cx"> };
</span><del>- 
</del><ins>+
</ins><span class="cx"> // Function to obtain the global memory pressure object.
</span><span class="cx"> WEBCORE_EXPORT MemoryPressureHandler&amp; memoryPressureHandler();
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformlinuxMemoryPressureHandlerLinuxcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebCore/platform/linux/MemoryPressureHandlerLinux.cpp (0 => 177216)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/linux/MemoryPressureHandlerLinux.cpp                                (rev 0)
+++ trunk/Source/WebCore/platform/linux/MemoryPressureHandlerLinux.cpp        2014-12-12 09:21:15 UTC (rev 177216)
</span><span class="lines">@@ -0,0 +1,241 @@
</span><ins>+/*
+ * Copyright (C) 2011, 2012 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.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;MemoryPressureHandler.h&quot;
+
+#if OS(LINUX)
+
+#include &quot;Logging.h&quot;
+
+#include &lt;fcntl.h&gt;
+#include &lt;malloc.h&gt;
+#include &lt;sys/eventfd.h&gt;
+#include &lt;sys/stat.h&gt;
+#include &lt;sys/types.h&gt;
+#include &lt;unistd.h&gt;
+#include &lt;wtf/CurrentTime.h&gt;
+#include &lt;wtf/Functional.h&gt;
+#include &lt;wtf/MainThread.h&gt;
+#include &lt;wtf/text/WTFString.h&gt;
+
+namespace WebCore {
+
+// Disable memory event reception for a minimum of s_minimumHoldOffTime
+// seconds after receiving an event. Don't let events fire any sooner than
+// s_holdOffMultiplier times the last cleanup processing time. Effectively
+// this is 1 / s_holdOffMultiplier percent of the time.
+// These value seems reasonable and testing verifies that it throttles frequent
+// low memory events, greatly reducing CPU usage.
+static const unsigned s_minimumHoldOffTime = 5;
+static const unsigned s_holdOffMultiplier = 20;
+
+static const char* s_cgroupMemoryPressureLevel = &quot;/sys/fs/cgroup/memory/memory.pressure_level&quot;;
+static const char* s_cgroupEventControl = &quot;/sys/fs/cgroup/memory/cgroup.event_control&quot;;
+static const char* s_processStatus = &quot;/proc/self/status&quot;;
+
+static inline String nextToken(FILE* file)
+{
+    if (!file)
+        return String();
+
+    static const unsigned bufferSize = 128;
+    char buffer[bufferSize] = {0, };
+    unsigned index = 0;
+    while (index &lt; bufferSize) {
+        char ch = fgetc(file);
+        if (ch == EOF || (isASCIISpace(ch) &amp;&amp; index)) // Break on non-initial ASCII space.
+            break;
+        if (!isASCIISpace(ch)) {
+            buffer[index] = ch;
+            index++;
+        }
+    }
+
+    return String(buffer);
+}
+
+MemoryPressureHandler::~MemoryPressureHandler()
+{
+    uninstall();
+}
+
+void MemoryPressureHandler::waitForMemoryPressureEvent(void*)
+{
+    ASSERT(!isMainThread());
+    int eventFD = memoryPressureHandler().m_eventFD;
+    if (!eventFD) {
+        LOG(MemoryPressure, &quot;Invalidate eventfd.&quot;);
+        return;
+    }
+
+    uint64_t buffer;
+    if (read(eventFD, &amp;buffer, sizeof(buffer)) &lt;= 0) {
+        LOG(MemoryPressure, &quot;Failed to read eventfd.&quot;);
+        return;
+    }
+
+    memoryPressureHandler().m_underMemoryPressure = true;
+    callOnMainThread(bind(&amp;MemoryPressureHandler::respondToMemoryPressure, &amp;memoryPressureHandler(), true));
+}
+
+inline void MemoryPressureHandler::logErrorAndCloseFDs(const char* log)
+{
+    if (log)
+        LOG(MemoryPressure, &quot;%s, error : %m&quot;, log);
+
+    if (m_eventFD) {
+        close(m_eventFD);
+        m_eventFD = 0;
+    }
+    if (m_pressureLevelFD) {
+        close(m_pressureLevelFD);
+        m_pressureLevelFD = 0;
+    }
+}
+
+void MemoryPressureHandler::install()
+{
+    if (m_installed)
+        return;
+
+    m_eventFD = eventfd(0, EFD_CLOEXEC);
+    if (m_eventFD == -1) {
+        LOG(MemoryPressure, &quot;eventfd() failed: %m&quot;);
+        return;
+    }
+
+    m_pressureLevelFD = open(s_cgroupMemoryPressureLevel, O_CLOEXEC | O_RDONLY);
+    if (m_pressureLevelFD == -1) {
+        logErrorAndCloseFDs(&quot;Failed to open memory.pressure_level&quot;);
+        return;
+    }
+
+    int fd = open(s_cgroupEventControl, O_CLOEXEC | O_WRONLY);
+    if (fd == -1) {
+        logErrorAndCloseFDs(&quot;Failed to open cgroup.event_control&quot;);
+        return;
+    }
+
+    char line[128] = {0, };
+    if (snprintf(line, sizeof(line), &quot;%d %d low&quot;, m_eventFD, m_pressureLevelFD) &lt; 0
+        || write(fd, line, strlen(line) + 1) &lt; 0) {
+        logErrorAndCloseFDs(&quot;Failed to write cgroup.event_control&quot;);
+        close(fd);
+        return;
+    }
+    close(fd);
+
+    m_threadID = createThread(waitForMemoryPressureEvent, this, &quot;WebCore: MemoryPressureHandler&quot;);
+    if (!m_threadID) {
+        logErrorAndCloseFDs(&quot;Failed to create a thread for MemoryPressureHandler&quot;);
+        return;
+    }
+
+    m_underMemoryPressure = false;
+    m_installed = true;
+}
+
+void MemoryPressureHandler::uninstall()
+{
+    if (!m_installed)
+        return;
+
+    if (m_threadID) {
+        detachThread(m_threadID);
+        m_threadID = 0;
+    }
+
+    logErrorAndCloseFDs(nullptr);
+    m_installed = false;
+}
+
+void MemoryPressureHandler::holdOffTimerFired()
+{
+    install();
+}
+
+void MemoryPressureHandler::holdOff(unsigned seconds)
+{
+    m_holdOffTimer.startOneShot(seconds);
+}
+
+void MemoryPressureHandler::respondToMemoryPressure(bool critical)
+{
+    uninstall();
+
+    double startTime = monotonicallyIncreasingTime();
+    m_lowMemoryHandler(critical);
+    unsigned holdOffTime = (monotonicallyIncreasingTime() - startTime) * s_holdOffMultiplier;
+    holdOff(std::max(holdOffTime, s_minimumHoldOffTime));
+}
+
+void MemoryPressureHandler::platformReleaseMemory(bool)
+{
+    ReliefLogger log(&quot;Run malloc_trim&quot;);
+    malloc_trim(0);
+}
+
+void MemoryPressureHandler::ReliefLogger::platformLog()
+{
+    size_t currentMemory = platformMemoryUsage();
+    if (currentMemory == static_cast&lt;size_t&gt;(-1) || m_initialMemory == static_cast&lt;size_t&gt;(-1)) {
+        LOG(MemoryPressure, &quot;%s (Unable to get dirty memory information for process)&quot;, m_logString);
+        return;
+    }
+
+    ssize_t memoryDiff = currentMemory - m_initialMemory;
+    if (memoryDiff &lt; 0)
+        LOG(MemoryPressure, &quot;Pressure relief: %s: -dirty %ld bytes (from %ld to %ld)&quot;, m_logString, (memoryDiff * -1), m_initialMemory, currentMemory);
+    else if (memoryDiff &gt; 0)
+        LOG(MemoryPressure, &quot;Pressure relief: %s: +dirty %ld bytes (from %ld to %ld)&quot;, m_logString, memoryDiff, m_initialMemory, currentMemory);
+    else
+        LOG(MemoryPressure, &quot;Pressure relief: %s: =dirty (at %ld bytes)&quot;, m_logString, currentMemory);
+}
+
+size_t MemoryPressureHandler::ReliefLogger::platformMemoryUsage()
+{
+    FILE* file = fopen(s_processStatus, &quot;r&quot;);
+    if (!file)
+        return static_cast&lt;size_t&gt;(-1);
+
+    size_t vmSize = static_cast&lt;size_t&gt;(-1); // KB
+    String token = nextToken(file);
+    while (!token.isEmpty()) {
+        if (token == &quot;VmSize:&quot;) {
+            vmSize = nextToken(file).toInt() * KB;
+            break;
+        }
+        token = nextToken(file);
+    }
+    fclose(file);
+
+    return vmSize;
+}
+
+} // namespace WebCore
+
+#endif // OS(LINUX)
</ins></span></pre>
</div>
</div>

</body>
</html>