diff options
Diffstat (limited to 'Source/WebCore/platform/linux')
5 files changed, 443 insertions, 172 deletions
diff --git a/Source/WebCore/platform/linux/CurrentProcessMemoryStatus.cpp b/Source/WebCore/platform/linux/CurrentProcessMemoryStatus.cpp new file mode 100644 index 000000000..36139ab6a --- /dev/null +++ b/Source/WebCore/platform/linux/CurrentProcessMemoryStatus.cpp @@ -0,0 +1,77 @@ +/* + * 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. ``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 "config.h" +#include "CurrentProcessMemoryStatus.h" + +#if OS(LINUX) + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +namespace WebCore { + +static inline size_t systemPageSize() +{ + static size_t pageSize = 0; + if (!pageSize) + pageSize = sysconf(_SC_PAGE_SIZE); + return pageSize; +} + +void currentProcessMemoryStatus(ProcessMemoryStatus& memoryStatus) +{ + FILE* file = fopen("/proc/self/statm", "r"); + if (!file) + return; + + char buffer[128]; + char* line = fgets(buffer, 128, file); + fclose(file); + if (!line) + return; + + size_t pageSize = systemPageSize(); + char* end = nullptr; + unsigned long long intValue = strtoull(line, &end, 10); + memoryStatus.size = intValue * pageSize; + intValue = strtoull(end, &end, 10); + memoryStatus.resident = intValue * pageSize; + intValue = strtoull(end, &end, 10); + memoryStatus.shared = intValue * pageSize; + intValue = strtoull(end, &end, 10); + memoryStatus.text = intValue * pageSize; + intValue = strtoull(end, &end, 10); + memoryStatus.lib = intValue * pageSize; + intValue = strtoull(end, &end, 10); + memoryStatus.data = intValue * pageSize; + intValue = strtoull(end, &end, 10); + memoryStatus.dt = intValue * pageSize; +} + +} // namespace WebCore + +#endif // OS(LINUX) diff --git a/Source/WebCore/platform/linux/CurrentProcessMemoryStatus.h b/Source/WebCore/platform/linux/CurrentProcessMemoryStatus.h new file mode 100644 index 000000000..b6d822b92 --- /dev/null +++ b/Source/WebCore/platform/linux/CurrentProcessMemoryStatus.h @@ -0,0 +1,46 @@ +/* + * 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. ``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. + */ + +#pragma once + +#if OS(LINUX) + +namespace WebCore { + +struct ProcessMemoryStatus { + size_t size { 0 }; + size_t resident { 0 }; + size_t shared { 0 }; + size_t text { 0 }; + size_t lib { 0 }; + size_t data { 0 }; + size_t dt { 0 }; +}; + +void currentProcessMemoryStatus(ProcessMemoryStatus&); + +} // namespace WebCore + +#endif // OS(LINUX) diff --git a/Source/WebCore/platform/linux/GamepadDeviceLinux.cpp b/Source/WebCore/platform/linux/GamepadDeviceLinux.cpp deleted file mode 100644 index c25bc1b5d..000000000 --- a/Source/WebCore/platform/linux/GamepadDeviceLinux.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2012 Zan Dobersek <zandobersek@gmail.com> - * - * 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 "GamepadDeviceLinux.h" - -#if ENABLE(GAMEPAD) - -#include <fcntl.h> -#include <sys/ioctl.h> -#include <unistd.h> -#include <wtf/text/CString.h> - -namespace WebCore { - -GamepadDeviceLinux::GamepadDeviceLinux(String deviceFile) - : m_fileDescriptor(-1) - , m_connected(false) - , m_lastTimestamp(0) -{ - // FIXME: Log errors when returning early. - m_fileDescriptor = open(deviceFile.utf8().data(), O_RDONLY | O_NONBLOCK); - if (m_fileDescriptor == -1) - return; - - char deviceName[1024]; - if (ioctl(m_fileDescriptor, JSIOCGNAME(sizeof(deviceName)), deviceName) < 0) - return; - m_deviceName = String(deviceName).simplifyWhiteSpace(); - - uint8_t numberOfAxes; - uint8_t numberOfButtons; - if (ioctl(m_fileDescriptor, JSIOCGAXES, &numberOfAxes) < 0 || ioctl(m_fileDescriptor, JSIOCGBUTTONS, &numberOfButtons) < 0) - return; - m_axes.fill(0.0, numberOfAxes); - m_buttons.fill(0.0, numberOfButtons); -} - -GamepadDeviceLinux::~GamepadDeviceLinux() -{ - if (m_fileDescriptor != -1) - close(m_fileDescriptor); -} - -void GamepadDeviceLinux::updateForEvent(struct js_event event) -{ - if (!(event.type & JS_EVENT_AXIS || event.type & JS_EVENT_BUTTON)) - return; - - // Mark the device as connected only if it is not yet connected, the event is not an initialization - // and the value is not 0 (indicating a genuine interaction with the device). - if (!m_connected && !(event.type & JS_EVENT_INIT) && event.value) - m_connected = true; - - if (event.type & JS_EVENT_AXIS) - m_axes[event.number] = normalizeAxisValue(event.value); - else if (event.type & JS_EVENT_BUTTON) - m_buttons[event.number] = normalizeButtonValue(event.value); - - m_lastTimestamp = event.time; -} - -float GamepadDeviceLinux::normalizeAxisValue(short value) -{ - // Normalize from range [-32767, 32767] into range [-1.0, 1.0] - return value / 32767.0f; -} - -float GamepadDeviceLinux::normalizeButtonValue(short value) -{ - // Normalize from range [0, 1] into range [0.0, 1.0] - return value / 1.0f; -} - -} // namespace WebCore - -#endif // ENABLE(GAMEPAD) diff --git a/Source/WebCore/platform/linux/GamepadDeviceLinux.h b/Source/WebCore/platform/linux/GamepadDeviceLinux.h deleted file mode 100644 index d485e83a9..000000000 --- a/Source/WebCore/platform/linux/GamepadDeviceLinux.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2012 Zan Dobersek <zandobersek@gmail.com> - * - * 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. - */ - -#ifndef GamepadDeviceLinux_h -#define GamepadDeviceLinux_h - -#if ENABLE(GAMEPAD) - -#include <linux/joystick.h> -#include <wtf/Vector.h> -#include <wtf/text/WTFString.h> - -namespace WebCore { - -class GamepadDeviceLinux { -public: - bool connected() { return m_connected; }; - - String id() { return m_deviceName; } - unsigned long long timestamp() { return m_lastTimestamp; } - - unsigned axesCount() { return m_axes.size(); } - float* axesData() { return m_axes.data(); } - - unsigned buttonsCount() { return m_buttons.size(); } - float* buttonsData() { return m_buttons.data(); } - -protected: - GamepadDeviceLinux(String deviceFile); - ~GamepadDeviceLinux(); - - void updateForEvent(struct js_event); - int m_fileDescriptor; - -private: - float normalizeAxisValue(short value); - float normalizeButtonValue(short value); - - bool m_connected; - String m_deviceName; - unsigned long long m_lastTimestamp; - - Vector<float> m_axes; - Vector<float> m_buttons; -}; - -} // namespace WebCore - -#endif // ENABLE(GAMEPAD) - -#endif // GamepadDeviceLinux_h diff --git a/Source/WebCore/platform/linux/MemoryPressureHandlerLinux.cpp b/Source/WebCore/platform/linux/MemoryPressureHandlerLinux.cpp new file mode 100644 index 000000000..4cd1bddf3 --- /dev/null +++ b/Source/WebCore/platform/linux/MemoryPressureHandlerLinux.cpp @@ -0,0 +1,320 @@ +/* + * 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 "config.h" +#include "MemoryPressureHandler.h" + +#if OS(LINUX) + +#include "CurrentProcessMemoryStatus.h" +#include "Logging.h" + +#include <errno.h> +#include <fcntl.h> +#include <malloc.h> +#include <sys/eventfd.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> +#include <wtf/CurrentTime.h> +#include <wtf/MainThread.h> +#include <wtf/text/WTFString.h> + +#if USE(GLIB) +#include <glib-unix.h> +#endif + +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. +// If after releasing the memory we don't free at least s_minimumBytesFreedToUseMinimumHoldOffTime, +// we wait longer to try again (s_maximumHoldOffTime). +// 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_maximumHoldOffTime = 30; +static const size_t s_minimumBytesFreedToUseMinimumHoldOffTime = 1 * MB; +static const unsigned s_holdOffMultiplier = 20; + +static const char* s_cgroupMemoryPressureLevel = "/sys/fs/cgroup/memory/memory.pressure_level"; +static const char* s_cgroupEventControl = "/sys/fs/cgroup/memory/cgroup.event_control"; + +#if USE(GLIB) +typedef struct { + GSource source; + gpointer fdTag; + GIOCondition condition; +} EventFDSource; + +static const unsigned eventFDSourceCondition = G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_NVAL; + +static GSourceFuncs eventFDSourceFunctions = { + nullptr, // prepare + nullptr, // check + // dispatch + [](GSource* source, GSourceFunc callback, gpointer userData) -> gboolean + { + EventFDSource* eventFDSource = reinterpret_cast<EventFDSource*>(source); + unsigned events = g_source_query_unix_fd(source, eventFDSource->fdTag) & eventFDSourceCondition; + if (events & G_IO_HUP || events & G_IO_ERR || events & G_IO_NVAL) + return G_SOURCE_REMOVE; + + gboolean returnValue = G_SOURCE_CONTINUE; + if (events & G_IO_IN) + returnValue = callback(userData); + g_source_set_ready_time(source, -1); + return returnValue; + }, + nullptr, // finalize + nullptr, // closure_callback + nullptr, // closure_marshall +}; +#endif + +MemoryPressureHandler::EventFDPoller::EventFDPoller(int fd, std::function<void ()>&& notifyHandler) + : m_fd(fd) + , m_notifyHandler(WTFMove(notifyHandler)) +{ +#if USE(GLIB) + m_source = adoptGRef(g_source_new(&eventFDSourceFunctions, sizeof(EventFDSource))); + g_source_set_name(m_source.get(), "WebCore: MemoryPressureHandler"); + if (!g_unix_set_fd_nonblocking(m_fd.value(), TRUE, nullptr)) { + LOG(MemoryPressure, "Failed to set eventfd nonblocking"); + return; + } + + EventFDSource* eventFDSource = reinterpret_cast<EventFDSource*>(m_source.get()); + eventFDSource->fdTag = g_source_add_unix_fd(m_source.get(), m_fd.value(), static_cast<GIOCondition>(eventFDSourceCondition)); + g_source_set_callback(m_source.get(), [](gpointer userData) -> gboolean { + static_cast<EventFDPoller*>(userData)->readAndNotify(); + return G_SOURCE_REMOVE; + }, this, nullptr); + g_source_attach(m_source.get(), nullptr); +#else + m_threadID = createThread("WebCore: MemoryPressureHandler", [this] { readAndNotify(); } +#endif +} + +MemoryPressureHandler::EventFDPoller::~EventFDPoller() +{ + m_fd = std::nullopt; +#if USE(GLIB) + g_source_destroy(m_source.get()); +#else + detachThread(m_threadID); +#endif +} + +static inline bool isFatalReadError(int error) +{ +#if USE(GLIB) + // We don't really need to read the buffer contents, if the poller + // notified us, but read would block or is no longer available, is + // enough to trigger the memory pressure handler. + return error != EAGAIN && error != EWOULDBLOCK; +#else + return true; +#endif +} + +void MemoryPressureHandler::EventFDPoller::readAndNotify() const +{ + if (!m_fd) { + LOG(MemoryPressure, "Invalidate eventfd."); + return; + } + + uint64_t buffer; + if (read(m_fd.value(), &buffer, sizeof(buffer)) == -1) { + if (isFatalReadError(errno)) { + LOG(MemoryPressure, "Failed to read eventfd."); + return; + } + } + + m_notifyHandler(); +} + +inline void MemoryPressureHandler::logErrorAndCloseFDs(const char* log) +{ + if (log) + LOG(MemoryPressure, "%s, error : %m", log); + + if (m_eventFD) { + close(m_eventFD.value()); + m_eventFD = std::nullopt; + } + if (m_pressureLevelFD) { + close(m_pressureLevelFD.value()); + m_pressureLevelFD = std::nullopt; + } +} + +bool MemoryPressureHandler::tryEnsureEventFD() +{ + 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 false; + } + m_eventFD = fd; + + fd = open(s_cgroupMemoryPressureLevel, O_CLOEXEC | O_RDONLY); + if (fd == -1) { + logErrorAndCloseFDs("Failed to open memory.pressure_level"); + return false; + } + m_pressureLevelFD = fd; + + fd = open(s_cgroupEventControl, O_CLOEXEC | O_WRONLY); + if (fd == -1) { + logErrorAndCloseFDs("Failed to open cgroup.event_control"); + return false; + } + + char line[128] = {0, }; + if (snprintf(line, sizeof(line), "%d %d low", m_eventFD.value(), m_pressureLevelFD.value()) < 0 + || write(fd, line, strlen(line) + 1) < 0) { + logErrorAndCloseFDs("Failed to write cgroup.event_control"); + close(fd); + 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 + // to get a detailed memory pressure level in the future, we should update here accordingly. + bool critical = true; + if (ReliefLogger::loggingEnabled()) + LOG(MemoryPressure, "Got memory pressure notification (%s)", critical ? "critical" : "non-critical"); + + setUnderMemoryPressure(critical); + if (isMainThread()) + respondToMemoryPressure(critical ? Critical::Yes : Critical::No); + else + RunLoop::main().dispatch([this, critical] { respondToMemoryPressure(critical ? Critical::Yes : Critical::No); }); + }); + + if (ReliefLogger::loggingEnabled() && isUnderMemoryPressure()) + LOG(MemoryPressure, "System is no longer under memory pressure."); + + setUnderMemoryPressure(false); + m_installed = true; +} + +void MemoryPressureHandler::uninstall() +{ + if (!m_installed) + return; + + m_holdOffTimer.stop(); + m_eventFDPoller = nullptr; + + if (m_pressureLevelFD) { + close(m_pressureLevelFD.value()); + m_pressureLevelFD = std::nullopt; + + // Only close the eventFD used for cgroups. + if (m_eventFD) { + close(m_eventFD.value()); + m_eventFD = std::nullopt; + } + } + + m_installed = false; +} + +void MemoryPressureHandler::holdOffTimerFired() +{ + install(); +} + +void MemoryPressureHandler::holdOff(unsigned seconds) +{ + m_holdOffTimer.startOneShot(seconds); +} + +static size_t processMemoryUsage() +{ + ProcessMemoryStatus memoryStatus; + currentProcessMemoryStatus(memoryStatus); + return (memoryStatus.resident - memoryStatus.shared); +} + +void MemoryPressureHandler::respondToMemoryPressure(Critical critical, Synchronous synchronous) +{ + uninstall(); + + double startTime = monotonicallyIncreasingTime(); + int64_t processMemory = processMemoryUsage(); + releaseMemory(critical, synchronous); + int64_t bytesFreed = processMemory - processMemoryUsage(); + unsigned holdOffTime = s_maximumHoldOffTime; + if (bytesFreed > 0 && static_cast<size_t>(bytesFreed) >= s_minimumBytesFreedToUseMinimumHoldOffTime) + holdOffTime = (monotonicallyIncreasingTime() - startTime) * s_holdOffMultiplier; + holdOff(std::max(holdOffTime, s_minimumHoldOffTime)); +} + +void MemoryPressureHandler::platformReleaseMemory(Critical) +{ +#ifdef __GLIBC__ + malloc_trim(0); +#endif +} + +std::optional<MemoryPressureHandler::ReliefLogger::MemoryUsage> MemoryPressureHandler::ReliefLogger::platformMemoryUsage() +{ + return MemoryUsage {processMemoryUsage(), 0}; +} + +void MemoryPressureHandler::setMemoryPressureMonitorHandle(int fd) +{ + ASSERT(!m_eventFD); + m_eventFD = fd; +} + +} // namespace WebCore + +#endif // OS(LINUX) |