Path: blob/main/contrib/llvm-project/lldb/source/Host/common/MemoryMonitor.cpp
213799 views
//===-- MemoryMonitor.cpp -------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Host/MemoryMonitor.h"9#include "lldb/Host/HostThread.h"10#include "lldb/Host/ThreadLauncher.h"11#include "lldb/Utility/LLDBLog.h"12#include "lldb/Utility/Log.h"13#include "llvm/ADT/ScopeExit.h"14#include "llvm/Support/Error.h"15#include <atomic>16#include <cstddef>17#include <cstdio>18#include <cstring>1920#if defined(__linux__)21#include <fcntl.h>22#include <poll.h>23#include <unistd.h>24#endif2526#if defined(_WIN32)27#include <windows.h>28#endif2930using namespace lldb_private;3132class MemoryMonitorPoll : public MemoryMonitor {33public:34using MemoryMonitor::MemoryMonitor;3536lldb::thread_result_t MonitorThread() {37#if defined(__linux__)38struct pollfd fds;39fds.fd = open("/proc/pressure/memory", O_RDWR | O_NONBLOCK);40if (fds.fd < 0)41return {};42fds.events = POLLPRI;4344auto cleanup = llvm::make_scope_exit([&]() { close(fds.fd); });4546// Detect a 50ms stall in a 2 second time window.47const char trig[] = "some 50000 2000000";48if (write(fds.fd, trig, strlen(trig) + 1) < 0)49return {};5051while (!m_done) {52int n = poll(&fds, 1, g_timeout);53if (n > 0) {54if (fds.revents & POLLERR)55return {};56if (fds.revents & POLLPRI)57m_callback();58}59}60#endif6162#if defined(_WIN32)63HANDLE low_memory_notification =64CreateMemoryResourceNotification(LowMemoryResourceNotification);65if (!low_memory_notification)66return {};6768while (!m_done) {69if (WaitForSingleObject(low_memory_notification, g_timeout) ==70WAIT_OBJECT_0) {71m_callback();72}73}74#endif7576return {};77}7879void Start() override {80llvm::Expected<HostThread> memory_monitor_thread =81ThreadLauncher::LaunchThread("lldb.debugger.memory-monitor",82[this] { return MonitorThread(); });83if (memory_monitor_thread) {84m_memory_monitor_thread = *memory_monitor_thread;85} else {86LLDB_LOG_ERROR(GetLog(LLDBLog::Host), memory_monitor_thread.takeError(),87"failed to launch host thread: {0}");88}89}9091void Stop() override {92if (m_memory_monitor_thread.IsJoinable()) {93m_done = true;94m_memory_monitor_thread.Join(nullptr);95}96}9798private:99static constexpr uint32_t g_timeout = 1000;100std::atomic<bool> m_done = false;101HostThread m_memory_monitor_thread;102};103104#if !defined(__APPLE__)105std::unique_ptr<MemoryMonitor> MemoryMonitor::Create(Callback callback) {106return std::make_unique<MemoryMonitorPoll>(callback);107}108#endif109110111