<!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>[203342] trunk/Source</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/203342">203342</a></dd>
<dt>Author</dt> <dd>carlosgc@webkit.org</dd>
<dt>Date</dt> <dd>2016-07-18 02:04:10 -0700 (Mon, 18 Jul 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>MemoryPressureHandler doesn't work if cgroups aren't present in Linux
https://bugs.webkit.org/show_bug.cgi?id=155255

Reviewed by Sergio Villar Senin.

Source/WebCore:

Allow to pass an eventFD file descriptor to the MemoryPressureHandler to be monitorized in case cgroups are not
available.

* platform/MemoryPressureHandler.h:
* platform/linux/MemoryPressureHandlerLinux.cpp:

Source/WebKit2:

There's no way to get notifications about memory pressure in Linux without using cgroups that doesn't require a
manual polling. We can get that information from /proc/meminfo, but that's not pollable so it requires to
manually check its contents in a loop sleeping for a while between checks. This means we would be waking up the
process on every poll iteration, most of the times for nothing. That's specially problematic on devices running
on battery. And taking into account that there's a memory pressure handler in every secondary process (Web,
Network and Plugin), we would be waking up all those process all the time. However, not having a memory pressure
handler is even more problematic than the manual polling.
This patch adds a class MemoryPressureMonitor to the manual polling of /proc/meminfo, but runs in the UI
process, to avoid the weakups in all other secondary processes, and uses an eventFD to notify all other
processes. It's only used in case cgroups is not available. The eventFD descriptor is sent to all other
processes at startup, and passed to the MemoryPressureHandler before install() is called for the first
time. To minimize the wakeups even in the UI process, the poll interval is calculated from 1 to 5 seconds
depending on the current memory used, so in case of low memory level we sleep for a longer time.
It's also important to make the memory calculations as accurate as possible to avoid cleaning resources in the
secondary processes unnecessarily.

* NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::initializeNetworkProcess): Pass the memory pressure monitor file descriptor to the MemoryPressureHandler.
* NetworkProcess/NetworkProcess.h:
* NetworkProcess/NetworkProcessCreationParameters.cpp:
(WebKit::NetworkProcessCreationParameters::encode): Encode memory pressure monitor handle.
(WebKit::NetworkProcessCreationParameters::decode): Decode memory pressure monitor handle.
* NetworkProcess/NetworkProcessCreationParameters.h:
* PlatformEfl.cmake: Add new file to compilation, and update include dirs.
* PlatformGTK.cmake: Ditto.
* PluginProcess/PluginProcess.cpp:
(WebKit::PluginProcess::initializePluginProcess): Pass the memory pressure monitor file descriptor to the MemoryPressureHandler.
* Shared/Plugins/PluginProcessCreationParameters.cpp:
(WebKit::PluginProcessCreationParameters::encode): Encode memory pressure monitor handle.
(WebKit::PluginProcessCreationParameters::decode): Decode memory pressure monitor handle.
* Shared/Plugins/PluginProcessCreationParameters.h:
* Shared/WebProcessCreationParameters.cpp:
(WebKit::WebProcessCreationParameters::encode): Encode memory pressure monitor handle.
(WebKit::WebProcessCreationParameters::decode): Decode memory pressure monitor handle.
* Shared/WebProcessCreationParameters.h:
* UIProcess/Plugins/PluginProcessProxy.cpp:
(WebKit::PluginProcessProxy::didFinishLaunching): Create the memory pressure monitor handle for the plugin
process if needed.
* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::ensureNetworkProcess): Create the memory pressure monitor handle for the network
process if needed.
(WebKit::WebProcessPool::createNewWebProcess): Create the memory pressure monitor handle for the web process if
needed.
* UIProcess/linux/MemoryPressureMonitor.cpp: Added.
(WebKit::lowWatermarkPages):
(WebKit::systemPageSize):
(WebKit::calculateMemoryAvailable):
(WebKit::systemMemoryUsedAsPercentage):
(WebKit::pollIntervalForUsedMemoryPercentage):
(WebKit::isSystemdMemoryPressureMonitorAvailable):
(WebKit::MemoryPressureMonitor::isEnabled):
(WebKit::MemoryPressureMonitor::singleton):
(WebKit::MemoryPressureMonitor::MemoryPressureMonitor):
(WebKit::MemoryPressureMonitor::createHandle):
* UIProcess/linux/MemoryPressureMonitor.h:
* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::initializeWebProcess): Pass the memory pressure monitor file descriptor to the MemoryPressureHandler.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCoreplatformMemoryPressureHandlerh">trunk/Source/WebCore/platform/MemoryPressureHandler.h</a></li>
<li><a href="#trunkSourceWebCoreplatformlinuxMemoryPressureHandlerLinuxcpp">trunk/Source/WebCore/platform/linux/MemoryPressureHandlerLinux.cpp</a></li>
<li><a href="#trunkSourceWebKit2ChangeLog">trunk/Source/WebKit2/ChangeLog</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkProcesscpp">trunk/Source/WebKit2/NetworkProcess/NetworkProcess.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkProcessh">trunk/Source/WebKit2/NetworkProcess/NetworkProcess.h</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkProcessCreationParameterscpp">trunk/Source/WebKit2/NetworkProcess/NetworkProcessCreationParameters.cpp</a></li>
<li><a href="#trunkSourceWebKit2NetworkProcessNetworkProcessCreationParametersh">trunk/Source/WebKit2/NetworkProcess/NetworkProcessCreationParameters.h</a></li>
<li><a href="#trunkSourceWebKit2PlatformEflcmake">trunk/Source/WebKit2/PlatformEfl.cmake</a></li>
<li><a href="#trunkSourceWebKit2PlatformGTKcmake">trunk/Source/WebKit2/PlatformGTK.cmake</a></li>
<li><a href="#trunkSourceWebKit2PluginProcessPluginProcesscpp">trunk/Source/WebKit2/PluginProcess/PluginProcess.cpp</a></li>
<li><a href="#trunkSourceWebKit2SharedPluginsPluginProcessCreationParameterscpp">trunk/Source/WebKit2/Shared/Plugins/PluginProcessCreationParameters.cpp</a></li>
<li><a href="#trunkSourceWebKit2SharedPluginsPluginProcessCreationParametersh">trunk/Source/WebKit2/Shared/Plugins/PluginProcessCreationParameters.h</a></li>
<li><a href="#trunkSourceWebKit2SharedWebProcessCreationParameterscpp">trunk/Source/WebKit2/Shared/WebProcessCreationParameters.cpp</a></li>
<li><a href="#trunkSourceWebKit2SharedWebProcessCreationParametersh">trunk/Source/WebKit2/Shared/WebProcessCreationParameters.h</a></li>
<li><a href="#trunkSourceWebKit2UIProcessPluginsPluginProcessProxycpp">trunk/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcessWebProcessPoolcpp">trunk/Source/WebKit2/UIProcess/WebProcessPool.cpp</a></li>
<li><a href="#trunkSourceWebKit2WebProcessWebProcesscpp">trunk/Source/WebKit2/WebProcess/WebProcess.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li>trunk/Source/WebKit2/UIProcess/linux/</li>
<li><a href="#trunkSourceWebKit2UIProcesslinuxMemoryPressureMonitorcpp">trunk/Source/WebKit2/UIProcess/linux/MemoryPressureMonitor.cpp</a></li>
<li><a href="#trunkSourceWebKit2UIProcesslinuxMemoryPressureMonitorh">trunk/Source/WebKit2/UIProcess/linux/MemoryPressureMonitor.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (203341 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2016-07-18 06:53:52 UTC (rev 203341)
+++ trunk/Source/WebCore/ChangeLog        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2016-07-18  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
+
+        MemoryPressureHandler doesn't work if cgroups aren't present in Linux
+        https://bugs.webkit.org/show_bug.cgi?id=155255
+
+        Reviewed by Sergio Villar Senin.
+
+        Allow to pass an eventFD file descriptor to the MemoryPressureHandler to be monitorized in case cgroups are not
+        available.
+
+        * platform/MemoryPressureHandler.h:
+        * platform/linux/MemoryPressureHandlerLinux.cpp:
+
</ins><span class="cx"> 2016-07-17  Gyuyoung Kim  &lt;gyuyoung.kim@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Clean up PassRefPtr uses in Modules/encryptedmedia, Modules/speech, and Modules/quota
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformMemoryPressureHandlerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/MemoryPressureHandler.h (203341 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/MemoryPressureHandler.h        2016-07-18 06:53:52 UTC (rev 203341)
+++ trunk/Source/WebCore/platform/MemoryPressureHandler.h        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -84,6 +84,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)
+    void setMemoryPressureMonitorHandle(int fd);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     class ReliefLogger {
</span><span class="lines">@@ -179,6 +181,7 @@
</span><span class="cx">     RunLoop::Timer&lt;MemoryPressureHandler&gt; m_holdOffTimer;
</span><span class="cx">     void holdOffTimerFired();
</span><span class="cx">     void logErrorAndCloseFDs(const char* error);
</span><ins>+    bool tryEnsureEventFD();
</ins><span class="cx"> #endif
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebCoreplatformlinuxMemoryPressureHandlerLinuxcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/platform/linux/MemoryPressureHandlerLinux.cpp (203341 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/platform/linux/MemoryPressureHandlerLinux.cpp        2016-07-18 06:53:52 UTC (rev 203341)
+++ trunk/Source/WebCore/platform/linux/MemoryPressureHandlerLinux.cpp        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -193,15 +193,16 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void MemoryPressureHandler::install()
</del><ins>+bool MemoryPressureHandler::tryEnsureEventFD()
</ins><span class="cx"> {
</span><del>-    if (m_installed || m_holdOffTimer.isActive())
-        return;
</del><ins>+    if (m_eventFD)
+        return true;
</ins><span class="cx"> 
</span><ins>+    // Try to use cgroups instead.
</ins><span class="cx">     int fd = eventfd(0, EFD_CLOEXEC);
</span><span class="cx">     if (fd == -1) {
</span><span class="cx">         LOG(MemoryPressure, &quot;eventfd() failed: %m&quot;);
</span><del>-        return;
</del><ins>+        return false;
</ins><span class="cx">     }
</span><span class="cx">     m_eventFD = fd;
</span><span class="cx"> 
</span><span class="lines">@@ -208,7 +209,7 @@
</span><span class="cx">     fd = open(s_cgroupMemoryPressureLevel, O_CLOEXEC | O_RDONLY);
</span><span class="cx">     if (fd == -1) {
</span><span class="cx">         logErrorAndCloseFDs(&quot;Failed to open memory.pressure_level&quot;);
</span><del>-        return;
</del><ins>+        return false;
</ins><span class="cx">     }
</span><span class="cx">     m_pressureLevelFD = fd;
</span><span class="cx"> 
</span><span class="lines">@@ -215,7 +216,7 @@
</span><span class="cx">     fd = open(s_cgroupEventControl, O_CLOEXEC | O_WRONLY);
</span><span class="cx">     if (fd == -1) {
</span><span class="cx">         logErrorAndCloseFDs(&quot;Failed to open cgroup.event_control&quot;);
</span><del>-        return;
</del><ins>+        return false;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     char line[128] = {0, };
</span><span class="lines">@@ -223,10 +224,21 @@
</span><span class="cx">         || write(fd, line, strlen(line) + 1) &lt; 0) {
</span><span class="cx">         logErrorAndCloseFDs(&quot;Failed to write cgroup.event_control&quot;);
</span><span class="cx">         close(fd);
</span><del>-        return;
</del><ins>+        return false;
</ins><span class="cx">     }
</span><span class="cx">     close(fd);
</span><span class="cx"> 
</span><ins>+    return true;
+}
+
+void MemoryPressureHandler::install()
+{
+    if (m_installed || m_holdOffTimer.isActive())
+        return;
+
+    if (!tryEnsureEventFD())
+        return;
+
</ins><span class="cx">     m_eventFDPoller = std::make_unique&lt;EventFDPoller&gt;(m_eventFD.value(), [this] {
</span><span class="cx">         // FIXME: Current memcg does not provide any way for users to know how serious the memory pressure is.
</span><span class="cx">         // So we assume all notifications from memcg are critical for now. If memcg had better inferfaces
</span><span class="lines">@@ -257,7 +269,17 @@
</span><span class="cx">     m_holdOffTimer.stop();
</span><span class="cx">     m_eventFDPoller = nullptr;
</span><span class="cx"> 
</span><del>-    logErrorAndCloseFDs(nullptr);
</del><ins>+    if (m_pressureLevelFD) {
+        close(m_pressureLevelFD.value());
+        m_pressureLevelFD = Nullopt;
+
+        // Only close the eventFD used for cgroups.
+        if (m_eventFD) {
+            close(m_eventFD.value());
+            m_eventFD = Nullopt;
+        }
+    }
+
</ins><span class="cx">     m_installed = false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -309,6 +331,12 @@
</span><span class="cx">     return vmSize;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void MemoryPressureHandler::setMemoryPressureMonitorHandle(int fd)
+{
+    ASSERT(!m_eventFD);
+    m_eventFD = fd;
+}
+
</ins><span class="cx"> } // namespace WebCore
</span><span class="cx"> 
</span><span class="cx"> #endif // OS(LINUX)
</span></span></pre></div>
<a id="trunkSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/ChangeLog (203341 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/ChangeLog        2016-07-18 06:53:52 UTC (rev 203341)
+++ trunk/Source/WebKit2/ChangeLog        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -1,3 +1,68 @@
</span><ins>+2016-07-18  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
+
+        MemoryPressureHandler doesn't work if cgroups aren't present in Linux
+        https://bugs.webkit.org/show_bug.cgi?id=155255
+
+        Reviewed by Sergio Villar Senin.
+
+        There's no way to get notifications about memory pressure in Linux without using cgroups that doesn't require a
+        manual polling. We can get that information from /proc/meminfo, but that's not pollable so it requires to
+        manually check its contents in a loop sleeping for a while between checks. This means we would be waking up the
+        process on every poll iteration, most of the times for nothing. That's specially problematic on devices running
+        on battery. And taking into account that there's a memory pressure handler in every secondary process (Web,
+        Network and Plugin), we would be waking up all those process all the time. However, not having a memory pressure
+        handler is even more problematic than the manual polling.
+        This patch adds a class MemoryPressureMonitor to the manual polling of /proc/meminfo, but runs in the UI
+        process, to avoid the weakups in all other secondary processes, and uses an eventFD to notify all other
+        processes. It's only used in case cgroups is not available. The eventFD descriptor is sent to all other
+        processes at startup, and passed to the MemoryPressureHandler before install() is called for the first
+        time. To minimize the wakeups even in the UI process, the poll interval is calculated from 1 to 5 seconds
+        depending on the current memory used, so in case of low memory level we sleep for a longer time.
+        It's also important to make the memory calculations as accurate as possible to avoid cleaning resources in the
+        secondary processes unnecessarily.
+
+        * NetworkProcess/NetworkProcess.cpp:
+        (WebKit::NetworkProcess::initializeNetworkProcess): Pass the memory pressure monitor file descriptor to the MemoryPressureHandler.
+        * NetworkProcess/NetworkProcess.h:
+        * NetworkProcess/NetworkProcessCreationParameters.cpp:
+        (WebKit::NetworkProcessCreationParameters::encode): Encode memory pressure monitor handle.
+        (WebKit::NetworkProcessCreationParameters::decode): Decode memory pressure monitor handle.
+        * NetworkProcess/NetworkProcessCreationParameters.h:
+        * PlatformEfl.cmake: Add new file to compilation, and update include dirs.
+        * PlatformGTK.cmake: Ditto.
+        * PluginProcess/PluginProcess.cpp:
+        (WebKit::PluginProcess::initializePluginProcess): Pass the memory pressure monitor file descriptor to the MemoryPressureHandler.
+        * Shared/Plugins/PluginProcessCreationParameters.cpp:
+        (WebKit::PluginProcessCreationParameters::encode): Encode memory pressure monitor handle.
+        (WebKit::PluginProcessCreationParameters::decode): Decode memory pressure monitor handle.
+        * Shared/Plugins/PluginProcessCreationParameters.h:
+        * Shared/WebProcessCreationParameters.cpp:
+        (WebKit::WebProcessCreationParameters::encode): Encode memory pressure monitor handle.
+        (WebKit::WebProcessCreationParameters::decode): Decode memory pressure monitor handle.
+        * Shared/WebProcessCreationParameters.h:
+        * UIProcess/Plugins/PluginProcessProxy.cpp:
+        (WebKit::PluginProcessProxy::didFinishLaunching): Create the memory pressure monitor handle for the plugin
+        process if needed.
+        * UIProcess/WebProcessPool.cpp:
+        (WebKit::WebProcessPool::ensureNetworkProcess): Create the memory pressure monitor handle for the network
+        process if needed.
+        (WebKit::WebProcessPool::createNewWebProcess): Create the memory pressure monitor handle for the web process if
+        needed.
+        * UIProcess/linux/MemoryPressureMonitor.cpp: Added.
+        (WebKit::lowWatermarkPages):
+        (WebKit::systemPageSize):
+        (WebKit::calculateMemoryAvailable):
+        (WebKit::systemMemoryUsedAsPercentage):
+        (WebKit::pollIntervalForUsedMemoryPercentage):
+        (WebKit::isSystemdMemoryPressureMonitorAvailable):
+        (WebKit::MemoryPressureMonitor::isEnabled):
+        (WebKit::MemoryPressureMonitor::singleton):
+        (WebKit::MemoryPressureMonitor::MemoryPressureMonitor):
+        (WebKit::MemoryPressureMonitor::createHandle):
+        * UIProcess/linux/MemoryPressureMonitor.h:
+        * WebProcess/WebProcess.cpp:
+        (WebKit::WebProcess::initializeWebProcess): Pass the memory pressure monitor file descriptor to the MemoryPressureHandler.
+
</ins><span class="cx"> 2016-07-17  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         REGRESSION(r202855): [GTK] ASSERTION FAILED: m_webPage.bounds().contains(bounds)
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkProcesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkProcess.cpp (203341 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkProcess.cpp        2016-07-18 06:53:52 UTC (rev 203341)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkProcess.cpp        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -193,7 +193,7 @@
</span><span class="cx">     WTF::releaseFastMallocFreeMemory();
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void NetworkProcess::initializeNetworkProcess(const NetworkProcessCreationParameters&amp; parameters)
</del><ins>+void NetworkProcess::initializeNetworkProcess(NetworkProcessCreationParameters&amp;&amp; parameters)
</ins><span class="cx"> {
</span><span class="cx">     platformInitializeNetworkProcess(parameters);
</span><span class="cx"> 
</span><span class="lines">@@ -202,6 +202,10 @@
</span><span class="cx">     m_suppressMemoryPressureHandler = parameters.shouldSuppressMemoryPressureHandler;
</span><span class="cx">     if (!m_suppressMemoryPressureHandler) {
</span><span class="cx">         auto&amp; memoryPressureHandler = MemoryPressureHandler::singleton();
</span><ins>+#if OS(LINUX)
+        if (parameters.memoryPressureMonitorHandle.fileDescriptor() != -1)
+            memoryPressureHandler.setMemoryPressureMonitorHandle(parameters.memoryPressureMonitorHandle.releaseFileDescriptor());
+#endif
</ins><span class="cx">         memoryPressureHandler.setLowMemoryHandler([this] (Critical critical, Synchronous) {
</span><span class="cx">             lowMemoryHandler(critical);
</span><span class="cx">         });
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkProcessh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkProcess.h (203341 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkProcess.h        2016-07-18 06:53:52 UTC (rev 203341)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkProcess.h        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -159,7 +159,7 @@
</span><span class="cx">     // Message Handlers
</span><span class="cx">     void didReceiveNetworkProcessMessage(IPC::Connection&amp;, IPC::MessageDecoder&amp;);
</span><span class="cx">     void didReceiveSyncNetworkProcessMessage(IPC::Connection&amp;, IPC::MessageDecoder&amp;, std::unique_ptr&lt;IPC::MessageEncoder&gt;&amp;);
</span><del>-    void initializeNetworkProcess(const NetworkProcessCreationParameters&amp;);
</del><ins>+    void initializeNetworkProcess(NetworkProcessCreationParameters&amp;&amp;);
</ins><span class="cx">     void createNetworkConnectionToWebProcess();
</span><span class="cx">     void destroyPrivateBrowsingSession(WebCore::SessionID);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkProcessCreationParameterscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkProcessCreationParameters.cpp (203341 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkProcessCreationParameters.cpp        2016-07-18 06:53:52 UTC (rev 203341)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkProcessCreationParameters.cpp        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -82,6 +82,9 @@
</span><span class="cx">     encoder &lt;&lt; ignoreTLSErrors;
</span><span class="cx">     encoder &lt;&lt; languages;
</span><span class="cx"> #endif
</span><ins>+#if OS(LINUX)
+    encoder &lt;&lt; memoryPressureMonitorHandle;
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool NetworkProcessCreationParameters::decode(IPC::ArgumentDecoder&amp; decoder, NetworkProcessCreationParameters&amp; result)
</span><span class="lines">@@ -158,6 +161,11 @@
</span><span class="cx">         return false;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if OS(LINUX)
+    if (!decoder.decode(result.memoryPressureMonitorHandle))
+        return false;
+#endif
+
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2NetworkProcessNetworkProcessCreationParametersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/NetworkProcess/NetworkProcessCreationParameters.h (203341 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/NetworkProcess/NetworkProcessCreationParameters.h        2016-07-18 06:53:52 UTC (rev 203341)
+++ trunk/Source/WebKit2/NetworkProcess/NetworkProcessCreationParameters.h        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #ifndef NetworkProcessCreationParameters_h
</span><span class="cx"> #define NetworkProcessCreationParameters_h
</span><span class="cx"> 
</span><ins>+#include &quot;Attachment.h&quot;
</ins><span class="cx"> #include &quot;CacheModel.h&quot;
</span><span class="cx"> #include &quot;SandboxExtension.h&quot;
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="lines">@@ -95,6 +96,10 @@
</span><span class="cx">     bool ignoreTLSErrors;
</span><span class="cx">     Vector&lt;String&gt; languages;
</span><span class="cx"> #endif
</span><ins>+
+#if OS(LINUX)
+    IPC::Attachment memoryPressureMonitorHandle;
+#endif
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2PlatformEflcmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/PlatformEfl.cmake (203341 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/PlatformEfl.cmake        2016-07-18 06:53:52 UTC (rev 203341)
+++ trunk/Source/WebKit2/PlatformEfl.cmake        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -171,6 +171,8 @@
</span><span class="cx">     UIProcess/gstreamer/InstallMissingMediaPluginsPermissionRequest.cpp
</span><span class="cx">     UIProcess/gstreamer/WebPageProxyGStreamer.cpp
</span><span class="cx"> 
</span><ins>+    UIProcess/linux/MemoryPressureMonitor.cpp
+
</ins><span class="cx">     UIProcess/soup/WebCookieManagerProxySoup.cpp
</span><span class="cx">     UIProcess/soup/WebProcessPoolSoup.cpp
</span><span class="cx"> 
</span><span class="lines">@@ -256,6 +258,7 @@
</span><span class="cx">     &quot;${WEBKIT2_DIR}/UIProcess/CoordinatedGraphics&quot;
</span><span class="cx">     &quot;${WEBKIT2_DIR}/UIProcess/Network/CustomProtocols/soup&quot;
</span><span class="cx">     &quot;${WEBKIT2_DIR}/UIProcess/efl&quot;
</span><ins>+    &quot;${WEBKIT2_DIR}/UIProcess/linux&quot;
</ins><span class="cx">     &quot;${WEBKIT2_DIR}/UIProcess/soup&quot;
</span><span class="cx">     &quot;${WEBKIT2_DIR}/WebProcess/efl&quot;
</span><span class="cx">     &quot;${WEBKIT2_DIR}/WebProcess/soup&quot;
</span></span></pre></div>
<a id="trunkSourceWebKit2PlatformGTKcmake"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/PlatformGTK.cmake (203341 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/PlatformGTK.cmake        2016-07-18 06:53:52 UTC (rev 203341)
+++ trunk/Source/WebKit2/PlatformGTK.cmake        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -273,6 +273,8 @@
</span><span class="cx"> 
</span><span class="cx">     UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp
</span><span class="cx"> 
</span><ins>+    UIProcess/linux/MemoryPressureMonitor.cpp
+
</ins><span class="cx">     UIProcess/Network/CustomProtocols/soup/CustomProtocolManagerProxySoup.cpp
</span><span class="cx">     UIProcess/Network/CustomProtocols/soup/WebSoupCustomProtocolRequestManager.cpp
</span><span class="cx">     UIProcess/Network/CustomProtocols/soup/WebSoupCustomProtocolRequestManagerClient.cpp
</span><span class="lines">@@ -513,6 +515,7 @@
</span><span class="cx">     &quot;${WEBKIT2_DIR}/UIProcess/Plugins/gtk&quot;
</span><span class="cx">     &quot;${WEBKIT2_DIR}/UIProcess/gstreamer&quot;
</span><span class="cx">     &quot;${WEBKIT2_DIR}/UIProcess/gtk&quot;
</span><ins>+    &quot;${WEBKIT2_DIR}/UIProcess/linux&quot;
</ins><span class="cx">     &quot;${WEBKIT2_DIR}/UIProcess/soup&quot;
</span><span class="cx">     &quot;${WEBKIT2_DIR}/WebProcess/InjectedBundle/API/gtk&quot;
</span><span class="cx">     &quot;${WEBKIT2_DIR}/WebProcess/Plugins/Netscape/unix&quot;
</span></span></pre></div>
<a id="trunkSourceWebKit2PluginProcessPluginProcesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/PluginProcess/PluginProcess.cpp (203341 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/PluginProcess/PluginProcess.cpp        2016-07-18 06:53:52 UTC (rev 203341)
+++ trunk/Source/WebKit2/PluginProcess/PluginProcess.cpp        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -71,13 +71,6 @@
</span><span class="cx"> {
</span><span class="cx">     m_pluginPath = parameters.extraInitializationData.get(&quot;plugin-path&quot;);
</span><span class="cx">     platformInitializeProcess(parameters);
</span><del>-
-    auto&amp; memoryPressureHandler = MemoryPressureHandler::singleton();
-    memoryPressureHandler.setLowMemoryHandler([this] (Critical, Synchronous) {
-        if (shouldTerminate())
-            terminate();
-    });
-    memoryPressureHandler.install();
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void PluginProcess::removeWebProcessConnection(WebProcessConnection* webProcessConnection)
</span><span class="lines">@@ -137,6 +130,17 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!m_pluginModule);
</span><span class="cx"> 
</span><ins>+    auto&amp; memoryPressureHandler = MemoryPressureHandler::singleton();
+#if OS(LINUX)
+    if (parameters.memoryPressureMonitorHandle.fileDescriptor() != -1)
+        memoryPressureHandler.setMemoryPressureMonitorHandle(parameters.memoryPressureMonitorHandle.releaseFileDescriptor());
+#endif
+    memoryPressureHandler.setLowMemoryHandler([this] (Critical, Synchronous) {
+        if (shouldTerminate())
+            terminate();
+    });
+    memoryPressureHandler.install();
+
</ins><span class="cx">     m_supportsAsynchronousPluginInitialization = parameters.supportsAsynchronousPluginInitialization;
</span><span class="cx">     setMinimumLifetime(parameters.minimumLifetime);
</span><span class="cx">     setTerminationTimeout(parameters.terminationTimeout);
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedPluginsPluginProcessCreationParameterscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/Plugins/PluginProcessCreationParameters.cpp (203341 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/Plugins/PluginProcessCreationParameters.cpp        2016-07-18 06:53:52 UTC (rev 203341)
+++ trunk/Source/WebKit2/Shared/Plugins/PluginProcessCreationParameters.cpp        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -51,6 +51,9 @@
</span><span class="cx">     IPC::encode(encoder, networkATSContext.get());
</span><span class="cx"> #endif
</span><span class="cx"> #endif
</span><ins>+#if OS(LINUX)
+    encoder &lt;&lt; memoryPressureMonitorHandle;
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool PluginProcessCreationParameters::decode(IPC::ArgumentDecoder&amp; decoder, PluginProcessCreationParameters&amp; result)
</span><span class="lines">@@ -71,6 +74,10 @@
</span><span class="cx">         return false;
</span><span class="cx"> #endif
</span><span class="cx"> #endif
</span><ins>+#if OS(LINUX)
+    if (!decoder.decode(result.memoryPressureMonitorHandle))
+        return false;
+#endif
</ins><span class="cx"> 
</span><span class="cx">     return true;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedPluginsPluginProcessCreationParametersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/Plugins/PluginProcessCreationParameters.h (203341 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/Plugins/PluginProcessCreationParameters.h        2016-07-18 06:53:52 UTC (rev 203341)
+++ trunk/Source/WebKit2/Shared/Plugins/PluginProcessCreationParameters.h        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -28,6 +28,7 @@
</span><span class="cx"> 
</span><span class="cx"> #if ENABLE(NETSCAPE_PLUGIN_API)
</span><span class="cx"> 
</span><ins>+#include &quot;Attachment.h&quot;
</ins><span class="cx"> #include &quot;PluginProcessAttributes.h&quot;
</span><span class="cx"> 
</span><span class="cx"> #if PLATFORM(COCOA)
</span><span class="lines">@@ -59,6 +60,9 @@
</span><span class="cx">     RetainPtr&lt;CFDataRef&gt; networkATSContext;
</span><span class="cx"> #endif
</span><span class="cx"> #endif
</span><ins>+#if OS(LINUX)
+    IPC::Attachment memoryPressureMonitorHandle;
+#endif
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedWebProcessCreationParameterscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/WebProcessCreationParameters.cpp (203341 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/WebProcessCreationParameters.cpp        2016-07-18 06:53:52 UTC (rev 203341)
+++ trunk/Source/WebKit2/Shared/WebProcessCreationParameters.cpp        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -141,6 +141,10 @@
</span><span class="cx"> #if TARGET_OS_IPHONE || (PLATFORM(MAC) &amp;&amp; __MAC_OS_X_VERSION_MIN_REQUIRED &gt;= 101100)
</span><span class="cx">     IPC::encode(encoder, networkATSContext.get());
</span><span class="cx"> #endif
</span><ins>+
+#if OS(LINUX)
+    encoder &lt;&lt; memoryPressureMonitorHandle;
+#endif
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool WebProcessCreationParameters::decode(IPC::ArgumentDecoder&amp; decoder, WebProcessCreationParameters&amp; parameters)
</span><span class="lines">@@ -296,6 +300,11 @@
</span><span class="cx">         return false;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if OS(LINUX)
+    if (!decoder.decode(parameters.memoryPressureMonitorHandle))
+        return false;
+#endif
+
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebKit2SharedWebProcessCreationParametersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/Shared/WebProcessCreationParameters.h (203341 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/Shared/WebProcessCreationParameters.h        2016-07-18 06:53:52 UTC (rev 203341)
+++ trunk/Source/WebKit2/Shared/WebProcessCreationParameters.h        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -166,6 +166,10 @@
</span><span class="cx"> #if TARGET_OS_IPHONE || (PLATFORM(MAC) &amp;&amp; __MAC_OS_X_VERSION_MIN_REQUIRED &gt;= 101100)
</span><span class="cx">     RetainPtr&lt;CFDataRef&gt; networkATSContext;
</span><span class="cx"> #endif
</span><ins>+
+#if OS(LINUX)
+    IPC::Attachment memoryPressureMonitorHandle;
+#endif
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace WebKit
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessPluginsPluginProcessProxycpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp (203341 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp        2016-07-18 06:53:52 UTC (rev 203341)
+++ trunk/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -38,6 +38,10 @@
</span><span class="cx"> #include &lt;WebCore/NotImplemented.h&gt;
</span><span class="cx"> #include &lt;wtf/RunLoop.h&gt;
</span><span class="cx"> 
</span><ins>+#if OS(LINUX)
+#include &quot;MemoryPressureMonitor.h&quot;
+#endif
+
</ins><span class="cx"> using namespace WebCore;
</span><span class="cx"> 
</span><span class="cx"> namespace WebKit {
</span><span class="lines">@@ -229,6 +233,12 @@
</span><span class="cx">         parameters.minimumLifetime = minimumLifetime;
</span><span class="cx">         parameters.terminationTimeout = shutdownTimeout;
</span><span class="cx">     }
</span><ins>+
+#if OS(LINUX)
+    if (MemoryPressureMonitor::isEnabled())
+        parameters.memoryPressureMonitorHandle = MemoryPressureMonitor::singleton().createHandle();
+#endif
+
</ins><span class="cx">     platformInitializePluginProcess(parameters);
</span><span class="cx"> 
</span><span class="cx">     // Initialize the plug-in host process.
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcessWebProcessPoolcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/UIProcess/WebProcessPool.cpp (203341 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/WebProcessPool.cpp        2016-07-18 06:53:52 UTC (rev 203341)
+++ trunk/Source/WebKit2/UIProcess/WebProcessPool.cpp        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -93,6 +93,10 @@
</span><span class="cx"> #include &quot;WebSoupCustomProtocolRequestManager.h&quot;
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if OS(LINUX)
+#include &quot;MemoryPressureMonitor.h&quot;
+#endif
+
</ins><span class="cx"> #ifndef NDEBUG
</span><span class="cx"> #include &lt;wtf/RefCountedLeakCounter.h&gt;
</span><span class="cx"> #endif
</span><span class="lines">@@ -370,6 +374,11 @@
</span><span class="cx">         SandboxExtension::createHandle(parentBundleDirectory, SandboxExtension::ReadOnly, parameters.parentBundleDirectoryExtensionHandle);
</span><span class="cx"> #endif
</span><span class="cx"> 
</span><ins>+#if OS(LINUX)
+    if (MemoryPressureMonitor::isEnabled())
+        parameters.memoryPressureMonitorHandle = MemoryPressureMonitor::singleton().createHandle();
+#endif
+
</ins><span class="cx">     parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession;
</span><span class="cx"> 
</span><span class="cx">     // Add any platform specific parameters
</span><span class="lines">@@ -626,6 +635,8 @@
</span><span class="cx"> 
</span><span class="cx"> #if OS(LINUX)
</span><span class="cx">     parameters.shouldEnableMemoryPressureReliefLogging = true;
</span><ins>+    if (MemoryPressureMonitor::isEnabled())
+        parameters.memoryPressureMonitorHandle = MemoryPressureMonitor::singleton().createHandle();
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     parameters.resourceLoadStatisticsEnabled = resourceLoadStatisticsEnabled();
</span></span></pre></div>
<a id="trunkSourceWebKit2UIProcesslinuxMemoryPressureMonitorcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/WebKit2/UIProcess/linux/MemoryPressureMonitor.cpp (0 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/linux/MemoryPressureMonitor.cpp                                (rev 0)
+++ trunk/Source/WebKit2/UIProcess/linux/MemoryPressureMonitor.cpp        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -0,0 +1,282 @@
</span><ins>+/*
+ * Copyright (C) 2016 Igalia S.L.
+ *
+ * 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. AND ITS CONTRIBUTORS ``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 ITS 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;MemoryPressureMonitor.h&quot;
+
+#if OS(LINUX)
+
+#include &quot;Attachment.h&quot;
+#include &lt;errno.h&gt;
+#include &lt;fcntl.h&gt;
+#include &lt;mutex&gt;
+#include &lt;stdlib.h&gt;
+#include &lt;string.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/Threading.h&gt;
+#include &lt;wtf/UniStdExtras.h&gt;
+
+namespace WebKit {
+
+static const size_t notSet = static_cast&lt;size_t&gt;(-1);
+
+static const double s_minPollingIntervalInSeconds = 1;
+static const double s_maxPollingIntervalInSeconds = 5;
+static const double s_minUsedMemoryPercentageForPolling = 50;
+static const double s_maxUsedMemoryPercentageForPolling = 90;
+static const int s_memoryPresurePercentageThreshold = 95;
+
+static size_t lowWatermarkPages()
+{
+    FILE* file = fopen(&quot;/proc/zoneinfo&quot;, &quot;r&quot;);
+    if (!file)
+        return notSet;
+
+    size_t low = 0;
+    bool inZone = false;
+    bool foundLow = false;
+    char buffer[128];
+    while (char* line = fgets(buffer, 128, file)) {
+        if (!strcmp(line, &quot;Node&quot;)) {
+            inZone = true;
+            foundLow = false;
+            continue;
+        }
+
+        char* token = strtok(line, &quot; &quot;);
+        if (!token)
+            continue;
+
+        if (!strcmp(token, &quot;low&quot;)) {
+            if (!inZone || foundLow) {
+                low = notSet;
+                break;
+            }
+            token = strtok(nullptr, &quot; &quot;);
+            if (!token) {
+                low = notSet;
+                break;
+            }
+            low += atoll(token);
+            foundLow = true;
+        }
+    }
+    fclose(file);
+
+    return low;
+}
+
+static inline size_t systemPageSize()
+{
+    static size_t pageSize = 0;
+    if (!pageSize)
+        pageSize = sysconf(_SC_PAGE_SIZE);
+    return pageSize;
+}
+
+// If MemAvailable was not present in /proc/meminfo, because it's an old kernel version,
+// we can do the same calculation with the information we have from meminfo and the low watermaks.
+// See https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773
+static size_t calculateMemoryAvailable(size_t memoryFree, size_t activeFile, size_t inactiveFile, size_t slabReclaimable)
+{
+    if (memoryFree == notSet || activeFile == notSet || inactiveFile == notSet || slabReclaimable == notSet)
+        return notSet;
+
+    size_t lowWatermark = lowWatermarkPages();
+    if (lowWatermark == notSet)
+        return notSet;
+
+    lowWatermark *= systemPageSize() / KB;
+
+    // Estimate the amount of memory available for userspace allocations, without causing swapping.
+    // Free memory cannot be taken below the low watermark, before the system starts swapping.
+    lowWatermark *= systemPageSize() / KB;
+    size_t memoryAvailable = memoryFree - lowWatermark;
+
+    // Not all the page cache can be freed, otherwise the system will start swapping. Assume at least
+    // half of the page cache, or the low watermark worth of cache, needs to stay.
+    size_t pageCache = activeFile + inactiveFile;
+    pageCache -= std::min(pageCache / 2, lowWatermark);
+    memoryAvailable += pageCache;
+
+    // Part of the reclaimable slab consists of items that are in use, and cannot be freed.
+    // Cap this estimate at the low watermark.
+    memoryAvailable += slabReclaimable - std::min(slabReclaimable / 2, lowWatermark);
+    return memoryAvailable;
+}
+
+static int systemMemoryUsedAsPercentage()
+{
+    FILE* file = fopen(&quot;/proc/meminfo&quot;, &quot;r&quot;);
+    if (!file)
+        return -1;
+
+    size_t memoryAvailable, memoryTotal, memoryFree, activeFile, inactiveFile, slabReclaimable;
+    memoryAvailable = memoryTotal = memoryFree = activeFile = inactiveFile = slabReclaimable = notSet;
+    char buffer[128];
+    while (char* line = fgets(buffer, 128, file)) {
+        char* token = strtok(line, &quot; &quot;);
+        if (!token)
+            break;
+
+        if (!strcmp(token, &quot;MemAvailable:&quot;)) {
+            if ((token = strtok(nullptr, &quot; &quot;))) {
+                memoryAvailable = atoll(token);
+                if (memoryTotal != notSet)
+                    break;
+            }
+        } else if (!strcmp(token, &quot;MemTotal:&quot;)) {
+            if ((token = strtok(nullptr, &quot; &quot;)))
+                memoryTotal = atoll(token);
+            else
+                break;
+        } else if (!strcmp(token, &quot;MemFree:&quot;)) {
+            if ((token = strtok(nullptr, &quot; &quot;)))
+                memoryFree = atoll(token);
+            else
+                break;
+        } else if (!strcmp(token, &quot;Active(file):&quot;)) {
+            if ((token = strtok(nullptr, &quot; &quot;)))
+                activeFile = atoll(token);
+            else
+                break;
+        } else if (!strcmp(token, &quot;Inactive(file):&quot;)) {
+            if ((token = strtok(nullptr, &quot; &quot;)))
+                inactiveFile = atoll(token);
+            else
+                break;
+        } else if (!strcmp(token, &quot;SReclaimable:&quot;)) {
+            if ((token = strtok(nullptr, &quot; &quot;)))
+                slabReclaimable = atoll(token);
+            else
+                break;
+        }
+
+        if (memoryTotal != notSet &amp;&amp; memoryFree != notSet &amp;&amp; activeFile != notSet &amp;&amp; inactiveFile != notSet &amp;&amp; slabReclaimable != notSet)
+            break;
+    }
+    fclose(file);
+
+    if (!memoryTotal || memoryTotal == notSet)
+        return -1;
+
+    if (memoryAvailable == notSet) {
+        memoryAvailable = calculateMemoryAvailable(memoryFree, activeFile, inactiveFile, slabReclaimable);
+        if (memoryAvailable == notSet)
+            return -1;
+    }
+
+    if (memoryAvailable &gt; memoryTotal)
+        return -1;
+
+    return ((memoryTotal - memoryAvailable) * 100) / memoryTotal;
+}
+
+static inline double pollIntervalForUsedMemoryPercentage(int usedPercentage)
+{
+    // Use a different poll interval depending on the currently memory used,
+    // to avoid polling too often when the system is under low memory usage.
+    if (usedPercentage &lt; s_minUsedMemoryPercentageForPolling)
+        return s_maxPollingIntervalInSeconds;
+
+    if (usedPercentage &gt;= s_maxUsedMemoryPercentageForPolling)
+        return s_minPollingIntervalInSeconds;
+
+    return s_minPollingIntervalInSeconds + (s_maxPollingIntervalInSeconds - s_minPollingIntervalInSeconds) *
+        ((usedPercentage - s_minUsedMemoryPercentageForPolling) / (s_maxUsedMemoryPercentageForPolling - s_minUsedMemoryPercentageForPolling));
+}
+
+static bool isSystemdMemoryPressureMonitorAvailable()
+{
+    int fd = open(&quot;/sys/fs/cgroup/memory/memory.pressure_level&quot;, O_CLOEXEC | O_RDONLY);
+    if (fd == -1)
+        return false;
+    close(fd);
+
+    fd = open(&quot;/sys/fs/cgroup/memory/cgroup.event_control&quot;, O_CLOEXEC | O_WRONLY);
+    if (fd == -1)
+        return false;
+    close(fd);
+
+    return true;
+}
+
+bool MemoryPressureMonitor::isEnabled()
+{
+    static std::once_flag onceFlag;
+    static bool enabled;
+    std::call_once(onceFlag, [] { enabled = !isSystemdMemoryPressureMonitorAvailable(); });
+    return enabled;
+}
+
+MemoryPressureMonitor&amp; MemoryPressureMonitor::singleton()
+{
+    ASSERT(isEnabled());
+    static NeverDestroyed&lt;MemoryPressureMonitor&gt; memoryMonitor;
+    return memoryMonitor;
+}
+
+MemoryPressureMonitor::MemoryPressureMonitor()
+    : m_eventFD(eventfd(0, EFD_CLOEXEC))
+{
+    if (m_eventFD == -1)
+        return;
+
+    ThreadIdentifier threadIdentifier = createThread(&quot;MemoryPressureMonitor&quot;, [this] {
+        double pollInterval = s_maxPollingIntervalInSeconds;
+        while (true) {
+            sleep(pollInterval);
+
+            int usedPercentage = systemMemoryUsedAsPercentage();
+            if (usedPercentage &gt;= s_memoryPresurePercentageThreshold) {
+                uint64_t fdEvent = 1;
+                ssize_t bytesWritten = write(m_eventFD, &amp;fdEvent, sizeof(uint64_t));
+                if (bytesWritten != sizeof(uint64_t)) {
+                    WTFLogAlways(&quot;Error writing to MemoryPressureMonitor eventFD: %s&quot;, strerror(errno));
+                    break;
+                }
+            }
+            pollInterval = pollIntervalForUsedMemoryPercentage(usedPercentage);
+        }
+        close(m_eventFD);
+    });
+    detachThread(threadIdentifier);
+}
+
+IPC::Attachment MemoryPressureMonitor::createHandle() const
+{
+    int duplicatedHandle = dupCloseOnExec(m_eventFD);
+    if (duplicatedHandle == -1)
+        return { };
+    return IPC::Attachment(duplicatedHandle);
+}
+
+} // namespace WebKit
+
+#endif // OS(LINUX)
</ins></span></pre></div>
<a id="trunkSourceWebKit2UIProcesslinuxMemoryPressureMonitorhfromrev203341trunkSourceWebKit2SharedPluginsPluginProcessCreationParametersh"></a>
<div class="copfile"><h4>Copied: trunk/Source/WebKit2/UIProcess/linux/MemoryPressureMonitor.h (from rev 203341, trunk/Source/WebKit2/Shared/Plugins/PluginProcessCreationParameters.h) (0 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/UIProcess/linux/MemoryPressureMonitor.h                                (rev 0)
+++ trunk/Source/WebKit2/UIProcess/linux/MemoryPressureMonitor.h        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -0,0 +1,58 @@
</span><ins>+/*
+ * Copyright (C) 2016 Igalia S.L.
+ *
+ * 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. AND ITS CONTRIBUTORS ``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 ITS 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.
+ */
+
+#pragma once
+
+#if OS(LINUX)
+
+#include &lt;wtf/NeverDestroyed.h&gt;
+#include &lt;wtf/Noncopyable.h&gt;
+
+namespace IPC {
+class Attachment;
+}
+
+namespace WebKit {
+
+class MemoryPressureMonitor {
+    WTF_MAKE_NONCOPYABLE(MemoryPressureMonitor);
+    friend class NeverDestroyed&lt;MemoryPressureMonitor&gt;;
+public:
+    static MemoryPressureMonitor&amp; singleton();
+    static bool isEnabled();
+
+    ~MemoryPressureMonitor();
+
+    IPC::Attachment createHandle() const;
+
+private:
+    MemoryPressureMonitor();
+
+    int m_eventFD { -1 };
+};
+
+} // namespace WebKit
+
+#endif // OS(LINUX)
</ins></span></pre></div>
<a id="trunkSourceWebKit2WebProcessWebProcesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebKit2/WebProcess/WebProcess.cpp (203341 => 203342)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebKit2/WebProcess/WebProcess.cpp        2016-07-18 06:53:52 UTC (rev 203341)
+++ trunk/Source/WebKit2/WebProcess/WebProcess.cpp        2016-07-18 09:04:10 UTC (rev 203342)
</span><span class="lines">@@ -267,7 +267,9 @@
</span><span class="cx">     ASSERT(m_pageMap.isEmpty());
</span><span class="cx"> 
</span><span class="cx"> #if OS(LINUX)
</span><del>-    WebCore::MemoryPressureHandler::ReliefLogger::setLoggingEnabled(parameters.shouldEnableMemoryPressureReliefLogging);
</del><ins>+    if (parameters.memoryPressureMonitorHandle.fileDescriptor() != -1)
+        MemoryPressureHandler::singleton().setMemoryPressureMonitorHandle(parameters.memoryPressureMonitorHandle.releaseFileDescriptor());
+    MemoryPressureHandler::ReliefLogger::setLoggingEnabled(parameters.shouldEnableMemoryPressureReliefLogging);
</ins><span class="cx"> #endif
</span><span class="cx"> 
</span><span class="cx">     platformInitializeWebProcess(WTFMove(parameters));
</span></span></pre>
</div>
</div>

</body>
</html>