Diff
Modified: trunk/Source/WebCore/ChangeLog (203341 => 203342)
--- 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)
@@ -1,3 +1,16 @@
+2016-07-18 Carlos Garcia Campos <[email protected]>
+
+ 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:
+
2016-07-17 Gyuyoung Kim <[email protected]>
Clean up PassRefPtr uses in Modules/encryptedmedia, Modules/speech, and Modules/quota
Modified: trunk/Source/WebCore/platform/MemoryPressureHandler.h (203341 => 203342)
--- 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)
@@ -84,6 +84,8 @@
WEBCORE_EXPORT void clearMemoryPressure();
WEBCORE_EXPORT bool shouldWaitForMemoryClearMessage();
void respondToMemoryPressureIfNeeded();
+#elif OS(LINUX)
+ void setMemoryPressureMonitorHandle(int fd);
#endif
class ReliefLogger {
@@ -179,6 +181,7 @@
RunLoop::Timer<MemoryPressureHandler> m_holdOffTimer;
void holdOffTimerFired();
void logErrorAndCloseFDs(const char* error);
+ bool tryEnsureEventFD();
#endif
};
Modified: trunk/Source/WebCore/platform/linux/MemoryPressureHandlerLinux.cpp (203341 => 203342)
--- 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)
@@ -193,15 +193,16 @@
}
}
-void MemoryPressureHandler::install()
+bool MemoryPressureHandler::tryEnsureEventFD()
{
- if (m_installed || m_holdOffTimer.isActive())
- return;
+ if (m_eventFD)
+ return true;
+ // Try to use cgroups instead.
int fd = eventfd(0, EFD_CLOEXEC);
if (fd == -1) {
LOG(MemoryPressure, "eventfd() failed: %m");
- return;
+ return false;
}
m_eventFD = fd;
@@ -208,7 +209,7 @@
fd = open(s_cgroupMemoryPressureLevel, O_CLOEXEC | O_RDONLY);
if (fd == -1) {
logErrorAndCloseFDs("Failed to open memory.pressure_level");
- return;
+ return false;
}
m_pressureLevelFD = fd;
@@ -215,7 +216,7 @@
fd = open(s_cgroupEventControl, O_CLOEXEC | O_WRONLY);
if (fd == -1) {
logErrorAndCloseFDs("Failed to open cgroup.event_control");
- return;
+ return false;
}
char line[128] = {0, };
@@ -223,10 +224,21 @@
|| write(fd, line, strlen(line) + 1) < 0) {
logErrorAndCloseFDs("Failed to write cgroup.event_control");
close(fd);
- return;
+ return false;
}
close(fd);
+ return true;
+}
+
+void MemoryPressureHandler::install()
+{
+ if (m_installed || m_holdOffTimer.isActive())
+ return;
+
+ if (!tryEnsureEventFD())
+ return;
+
m_eventFDPoller = std::make_unique<EventFDPoller>(m_eventFD.value(), [this] {
// FIXME: Current memcg does not provide any way for users to know how serious the memory pressure is.
// So we assume all notifications from memcg are critical for now. If memcg had better inferfaces
@@ -257,7 +269,17 @@
m_holdOffTimer.stop();
m_eventFDPoller = nullptr;
- logErrorAndCloseFDs(nullptr);
+ 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;
+ }
+ }
+
m_installed = false;
}
@@ -309,6 +331,12 @@
return vmSize;
}
+void MemoryPressureHandler::setMemoryPressureMonitorHandle(int fd)
+{
+ ASSERT(!m_eventFD);
+ m_eventFD = fd;
+}
+
} // namespace WebCore
#endif // OS(LINUX)
Modified: trunk/Source/WebKit2/ChangeLog (203341 => 203342)
--- 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)
@@ -1,3 +1,68 @@
+2016-07-18 Carlos Garcia Campos <[email protected]>
+
+ 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.
+
2016-07-17 Carlos Garcia Campos <[email protected]>
REGRESSION(r202855): [GTK] ASSERTION FAILED: m_webPage.bounds().contains(bounds)
Modified: trunk/Source/WebKit2/NetworkProcess/NetworkProcess.cpp (203341 => 203342)
--- 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)
@@ -193,7 +193,7 @@
WTF::releaseFastMallocFreeMemory();
}
-void NetworkProcess::initializeNetworkProcess(const NetworkProcessCreationParameters& parameters)
+void NetworkProcess::initializeNetworkProcess(NetworkProcessCreationParameters&& parameters)
{
platformInitializeNetworkProcess(parameters);
@@ -202,6 +202,10 @@
m_suppressMemoryPressureHandler = parameters.shouldSuppressMemoryPressureHandler;
if (!m_suppressMemoryPressureHandler) {
auto& memoryPressureHandler = MemoryPressureHandler::singleton();
+#if OS(LINUX)
+ if (parameters.memoryPressureMonitorHandle.fileDescriptor() != -1)
+ memoryPressureHandler.setMemoryPressureMonitorHandle(parameters.memoryPressureMonitorHandle.releaseFileDescriptor());
+#endif
memoryPressureHandler.setLowMemoryHandler([this] (Critical critical, Synchronous) {
lowMemoryHandler(critical);
});
Modified: trunk/Source/WebKit2/NetworkProcess/NetworkProcess.h (203341 => 203342)
--- 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)
@@ -159,7 +159,7 @@
// Message Handlers
void didReceiveNetworkProcessMessage(IPC::Connection&, IPC::MessageDecoder&);
void didReceiveSyncNetworkProcessMessage(IPC::Connection&, IPC::MessageDecoder&, std::unique_ptr<IPC::MessageEncoder>&);
- void initializeNetworkProcess(const NetworkProcessCreationParameters&);
+ void initializeNetworkProcess(NetworkProcessCreationParameters&&);
void createNetworkConnectionToWebProcess();
void destroyPrivateBrowsingSession(WebCore::SessionID);
Modified: trunk/Source/WebKit2/NetworkProcess/NetworkProcessCreationParameters.cpp (203341 => 203342)
--- 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)
@@ -82,6 +82,9 @@
encoder << ignoreTLSErrors;
encoder << languages;
#endif
+#if OS(LINUX)
+ encoder << memoryPressureMonitorHandle;
+#endif
}
bool NetworkProcessCreationParameters::decode(IPC::ArgumentDecoder& decoder, NetworkProcessCreationParameters& result)
@@ -158,6 +161,11 @@
return false;
#endif
+#if OS(LINUX)
+ if (!decoder.decode(result.memoryPressureMonitorHandle))
+ return false;
+#endif
+
return true;
}
Modified: trunk/Source/WebKit2/NetworkProcess/NetworkProcessCreationParameters.h (203341 => 203342)
--- 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)
@@ -26,6 +26,7 @@
#ifndef NetworkProcessCreationParameters_h
#define NetworkProcessCreationParameters_h
+#include "Attachment.h"
#include "CacheModel.h"
#include "SandboxExtension.h"
#include <wtf/Vector.h>
@@ -95,6 +96,10 @@
bool ignoreTLSErrors;
Vector<String> languages;
#endif
+
+#if OS(LINUX)
+ IPC::Attachment memoryPressureMonitorHandle;
+#endif
};
} // namespace WebKit
Modified: trunk/Source/WebKit2/PlatformEfl.cmake (203341 => 203342)
--- 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)
@@ -171,6 +171,8 @@
UIProcess/gstreamer/InstallMissingMediaPluginsPermissionRequest.cpp
UIProcess/gstreamer/WebPageProxyGStreamer.cpp
+ UIProcess/linux/MemoryPressureMonitor.cpp
+
UIProcess/soup/WebCookieManagerProxySoup.cpp
UIProcess/soup/WebProcessPoolSoup.cpp
@@ -256,6 +258,7 @@
"${WEBKIT2_DIR}/UIProcess/CoordinatedGraphics"
"${WEBKIT2_DIR}/UIProcess/Network/CustomProtocols/soup"
"${WEBKIT2_DIR}/UIProcess/efl"
+ "${WEBKIT2_DIR}/UIProcess/linux"
"${WEBKIT2_DIR}/UIProcess/soup"
"${WEBKIT2_DIR}/WebProcess/efl"
"${WEBKIT2_DIR}/WebProcess/soup"
Modified: trunk/Source/WebKit2/PlatformGTK.cmake (203341 => 203342)
--- 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)
@@ -273,6 +273,8 @@
UIProcess/Launcher/gtk/ProcessLauncherGtk.cpp
+ UIProcess/linux/MemoryPressureMonitor.cpp
+
UIProcess/Network/CustomProtocols/soup/CustomProtocolManagerProxySoup.cpp
UIProcess/Network/CustomProtocols/soup/WebSoupCustomProtocolRequestManager.cpp
UIProcess/Network/CustomProtocols/soup/WebSoupCustomProtocolRequestManagerClient.cpp
@@ -513,6 +515,7 @@
"${WEBKIT2_DIR}/UIProcess/Plugins/gtk"
"${WEBKIT2_DIR}/UIProcess/gstreamer"
"${WEBKIT2_DIR}/UIProcess/gtk"
+ "${WEBKIT2_DIR}/UIProcess/linux"
"${WEBKIT2_DIR}/UIProcess/soup"
"${WEBKIT2_DIR}/WebProcess/InjectedBundle/API/gtk"
"${WEBKIT2_DIR}/WebProcess/Plugins/Netscape/unix"
Modified: trunk/Source/WebKit2/PluginProcess/PluginProcess.cpp (203341 => 203342)
--- 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)
@@ -71,13 +71,6 @@
{
m_pluginPath = parameters.extraInitializationData.get("plugin-path");
platformInitializeProcess(parameters);
-
- auto& memoryPressureHandler = MemoryPressureHandler::singleton();
- memoryPressureHandler.setLowMemoryHandler([this] (Critical, Synchronous) {
- if (shouldTerminate())
- terminate();
- });
- memoryPressureHandler.install();
}
void PluginProcess::removeWebProcessConnection(WebProcessConnection* webProcessConnection)
@@ -137,6 +130,17 @@
{
ASSERT(!m_pluginModule);
+ auto& 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();
+
m_supportsAsynchronousPluginInitialization = parameters.supportsAsynchronousPluginInitialization;
setMinimumLifetime(parameters.minimumLifetime);
setTerminationTimeout(parameters.terminationTimeout);
Modified: trunk/Source/WebKit2/Shared/Plugins/PluginProcessCreationParameters.cpp (203341 => 203342)
--- 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)
@@ -51,6 +51,9 @@
IPC::encode(encoder, networkATSContext.get());
#endif
#endif
+#if OS(LINUX)
+ encoder << memoryPressureMonitorHandle;
+#endif
}
bool PluginProcessCreationParameters::decode(IPC::ArgumentDecoder& decoder, PluginProcessCreationParameters& result)
@@ -71,6 +74,10 @@
return false;
#endif
#endif
+#if OS(LINUX)
+ if (!decoder.decode(result.memoryPressureMonitorHandle))
+ return false;
+#endif
return true;
}
Modified: trunk/Source/WebKit2/Shared/Plugins/PluginProcessCreationParameters.h (203341 => 203342)
--- 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)
@@ -28,6 +28,7 @@
#if ENABLE(NETSCAPE_PLUGIN_API)
+#include "Attachment.h"
#include "PluginProcessAttributes.h"
#if PLATFORM(COCOA)
@@ -59,6 +60,9 @@
RetainPtr<CFDataRef> networkATSContext;
#endif
#endif
+#if OS(LINUX)
+ IPC::Attachment memoryPressureMonitorHandle;
+#endif
};
} // namespace WebKit
Modified: trunk/Source/WebKit2/Shared/WebProcessCreationParameters.cpp (203341 => 203342)
--- 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)
@@ -141,6 +141,10 @@
#if TARGET_OS_IPHONE || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
IPC::encode(encoder, networkATSContext.get());
#endif
+
+#if OS(LINUX)
+ encoder << memoryPressureMonitorHandle;
+#endif
}
bool WebProcessCreationParameters::decode(IPC::ArgumentDecoder& decoder, WebProcessCreationParameters& parameters)
@@ -296,6 +300,11 @@
return false;
#endif
+#if OS(LINUX)
+ if (!decoder.decode(parameters.memoryPressureMonitorHandle))
+ return false;
+#endif
+
return true;
}
Modified: trunk/Source/WebKit2/Shared/WebProcessCreationParameters.h (203341 => 203342)
--- 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)
@@ -166,6 +166,10 @@
#if TARGET_OS_IPHONE || (PLATFORM(MAC) && __MAC_OS_X_VERSION_MIN_REQUIRED >= 101100)
RetainPtr<CFDataRef> networkATSContext;
#endif
+
+#if OS(LINUX)
+ IPC::Attachment memoryPressureMonitorHandle;
+#endif
};
} // namespace WebKit
Modified: trunk/Source/WebKit2/UIProcess/Plugins/PluginProcessProxy.cpp (203341 => 203342)
--- 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)
@@ -38,6 +38,10 @@
#include <WebCore/NotImplemented.h>
#include <wtf/RunLoop.h>
+#if OS(LINUX)
+#include "MemoryPressureMonitor.h"
+#endif
+
using namespace WebCore;
namespace WebKit {
@@ -229,6 +233,12 @@
parameters.minimumLifetime = minimumLifetime;
parameters.terminationTimeout = shutdownTimeout;
}
+
+#if OS(LINUX)
+ if (MemoryPressureMonitor::isEnabled())
+ parameters.memoryPressureMonitorHandle = MemoryPressureMonitor::singleton().createHandle();
+#endif
+
platformInitializePluginProcess(parameters);
// Initialize the plug-in host process.
Modified: trunk/Source/WebKit2/UIProcess/WebProcessPool.cpp (203341 => 203342)
--- 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)
@@ -93,6 +93,10 @@
#include "WebSoupCustomProtocolRequestManager.h"
#endif
+#if OS(LINUX)
+#include "MemoryPressureMonitor.h"
+#endif
+
#ifndef NDEBUG
#include <wtf/RefCountedLeakCounter.h>
#endif
@@ -370,6 +374,11 @@
SandboxExtension::createHandle(parentBundleDirectory, SandboxExtension::ReadOnly, parameters.parentBundleDirectoryExtensionHandle);
#endif
+#if OS(LINUX)
+ if (MemoryPressureMonitor::isEnabled())
+ parameters.memoryPressureMonitorHandle = MemoryPressureMonitor::singleton().createHandle();
+#endif
+
parameters.shouldUseTestingNetworkSession = m_shouldUseTestingNetworkSession;
// Add any platform specific parameters
@@ -626,6 +635,8 @@
#if OS(LINUX)
parameters.shouldEnableMemoryPressureReliefLogging = true;
+ if (MemoryPressureMonitor::isEnabled())
+ parameters.memoryPressureMonitorHandle = MemoryPressureMonitor::singleton().createHandle();
#endif
parameters.resourceLoadStatisticsEnabled = resourceLoadStatisticsEnabled();
Added: trunk/Source/WebKit2/UIProcess/linux/MemoryPressureMonitor.cpp (0 => 203342)
--- 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)
@@ -0,0 +1,282 @@
+/*
+ * 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 "config.h"
+#include "MemoryPressureMonitor.h"
+
+#if OS(LINUX)
+
+#include "Attachment.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <mutex>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/eventfd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <wtf/CurrentTime.h>
+#include <wtf/Threading.h>
+#include <wtf/UniStdExtras.h>
+
+namespace WebKit {
+
+static const size_t notSet = static_cast<size_t>(-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("/proc/zoneinfo", "r");
+ 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, "Node")) {
+ inZone = true;
+ foundLow = false;
+ continue;
+ }
+
+ char* token = strtok(line, " ");
+ if (!token)
+ continue;
+
+ if (!strcmp(token, "low")) {
+ if (!inZone || foundLow) {
+ low = notSet;
+ break;
+ }
+ token = strtok(nullptr, " ");
+ 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("/proc/meminfo", "r");
+ 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, " ");
+ if (!token)
+ break;
+
+ if (!strcmp(token, "MemAvailable:")) {
+ if ((token = strtok(nullptr, " "))) {
+ memoryAvailable = atoll(token);
+ if (memoryTotal != notSet)
+ break;
+ }
+ } else if (!strcmp(token, "MemTotal:")) {
+ if ((token = strtok(nullptr, " ")))
+ memoryTotal = atoll(token);
+ else
+ break;
+ } else if (!strcmp(token, "MemFree:")) {
+ if ((token = strtok(nullptr, " ")))
+ memoryFree = atoll(token);
+ else
+ break;
+ } else if (!strcmp(token, "Active(file):")) {
+ if ((token = strtok(nullptr, " ")))
+ activeFile = atoll(token);
+ else
+ break;
+ } else if (!strcmp(token, "Inactive(file):")) {
+ if ((token = strtok(nullptr, " ")))
+ inactiveFile = atoll(token);
+ else
+ break;
+ } else if (!strcmp(token, "SReclaimable:")) {
+ if ((token = strtok(nullptr, " ")))
+ slabReclaimable = atoll(token);
+ else
+ break;
+ }
+
+ if (memoryTotal != notSet && memoryFree != notSet && activeFile != notSet && inactiveFile != notSet && 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 > 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 < s_minUsedMemoryPercentageForPolling)
+ return s_maxPollingIntervalInSeconds;
+
+ if (usedPercentage >= 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("/sys/fs/cgroup/memory/memory.pressure_level", O_CLOEXEC | O_RDONLY);
+ if (fd == -1)
+ return false;
+ close(fd);
+
+ fd = open("/sys/fs/cgroup/memory/cgroup.event_control", 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& MemoryPressureMonitor::singleton()
+{
+ ASSERT(isEnabled());
+ static NeverDestroyed<MemoryPressureMonitor> memoryMonitor;
+ return memoryMonitor;
+}
+
+MemoryPressureMonitor::MemoryPressureMonitor()
+ : m_eventFD(eventfd(0, EFD_CLOEXEC))
+{
+ if (m_eventFD == -1)
+ return;
+
+ ThreadIdentifier threadIdentifier = createThread("MemoryPressureMonitor", [this] {
+ double pollInterval = s_maxPollingIntervalInSeconds;
+ while (true) {
+ sleep(pollInterval);
+
+ int usedPercentage = systemMemoryUsedAsPercentage();
+ if (usedPercentage >= s_memoryPresurePercentageThreshold) {
+ uint64_t fdEvent = 1;
+ ssize_t bytesWritten = write(m_eventFD, &fdEvent, sizeof(uint64_t));
+ if (bytesWritten != sizeof(uint64_t)) {
+ WTFLogAlways("Error writing to MemoryPressureMonitor eventFD: %s", 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)
Copied: trunk/Source/WebKit2/UIProcess/linux/MemoryPressureMonitor.h (from rev 203341, trunk/Source/WebKit2/Shared/Plugins/PluginProcessCreationParameters.h) (0 => 203342)
--- 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)
@@ -0,0 +1,58 @@
+/*
+ * 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 <wtf/NeverDestroyed.h>
+#include <wtf/Noncopyable.h>
+
+namespace IPC {
+class Attachment;
+}
+
+namespace WebKit {
+
+class MemoryPressureMonitor {
+ WTF_MAKE_NONCOPYABLE(MemoryPressureMonitor);
+ friend class NeverDestroyed<MemoryPressureMonitor>;
+public:
+ static MemoryPressureMonitor& singleton();
+ static bool isEnabled();
+
+ ~MemoryPressureMonitor();
+
+ IPC::Attachment createHandle() const;
+
+private:
+ MemoryPressureMonitor();
+
+ int m_eventFD { -1 };
+};
+
+} // namespace WebKit
+
+#endif // OS(LINUX)
Modified: trunk/Source/WebKit2/WebProcess/WebProcess.cpp (203341 => 203342)
--- 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)
@@ -267,7 +267,9 @@
ASSERT(m_pageMap.isEmpty());
#if OS(LINUX)
- WebCore::MemoryPressureHandler::ReliefLogger::setLoggingEnabled(parameters.shouldEnableMemoryPressureReliefLogging);
+ if (parameters.memoryPressureMonitorHandle.fileDescriptor() != -1)
+ MemoryPressureHandler::singleton().setMemoryPressureMonitorHandle(parameters.memoryPressureMonitorHandle.releaseFileDescriptor());
+ MemoryPressureHandler::ReliefLogger::setLoggingEnabled(parameters.shouldEnableMemoryPressureReliefLogging);
#endif
platformInitializeWebProcess(WTFMove(parameters));