brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.8 KiB · 932fa9c Raw
110 lines · cpp
1//===-- MemoryMonitor.cpp -------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Host/MemoryMonitor.h"10#include "lldb/Host/HostThread.h"11#include "lldb/Host/ThreadLauncher.h"12#include "lldb/Utility/LLDBLog.h"13#include "lldb/Utility/Log.h"14#include "llvm/ADT/ScopeExit.h"15#include "llvm/Support/Error.h"16#include <atomic>17#include <cstddef>18#include <cstdio>19#include <cstring>20 21#if defined(__linux__)22#include <fcntl.h>23#include <poll.h>24#include <unistd.h>25#endif26 27#if defined(_WIN32)28#include <windows.h>29#endif30 31using namespace lldb_private;32 33class MemoryMonitorPoll : public MemoryMonitor {34public:35  using MemoryMonitor::MemoryMonitor;36 37  lldb::thread_result_t MonitorThread() {38#if defined(__linux__)39    struct pollfd fds;40    fds.fd = open("/proc/pressure/memory", O_RDWR | O_NONBLOCK);41    if (fds.fd < 0)42      return {};43    fds.events = POLLPRI;44 45    auto cleanup = llvm::make_scope_exit([&]() { close(fds.fd); });46 47    // Detect a 50ms stall in a 2 second time window.48    const char trig[] = "some 50000 2000000";49    if (write(fds.fd, trig, strlen(trig) + 1) < 0)50      return {};51 52    while (!m_done) {53      int n = poll(&fds, 1, g_timeout);54      if (n > 0) {55        if (fds.revents & POLLERR)56          return {};57        if (fds.revents & POLLPRI)58          m_callback();59      }60    }61#endif62 63#if defined(_WIN32)64    HANDLE low_memory_notification =65        CreateMemoryResourceNotification(LowMemoryResourceNotification);66    if (!low_memory_notification)67      return {};68 69    while (!m_done) {70      if (WaitForSingleObject(low_memory_notification, g_timeout) ==71          WAIT_OBJECT_0) {72        m_callback();73      }74    }75#endif76 77    return {};78  }79 80  void Start() override {81    llvm::Expected<HostThread> memory_monitor_thread =82        ThreadLauncher::LaunchThread("lldb.debugger.memory-monitor",83                                     [this] { return MonitorThread(); });84    if (memory_monitor_thread) {85      m_memory_monitor_thread = *memory_monitor_thread;86    } else {87      LLDB_LOG_ERROR(GetLog(LLDBLog::Host), memory_monitor_thread.takeError(),88                     "failed to launch host thread: {0}");89    }90  }91 92  void Stop() override {93    if (m_memory_monitor_thread.IsJoinable()) {94      m_done = true;95      m_memory_monitor_thread.Join(nullptr);96    }97  }98 99private:100  static constexpr uint32_t g_timeout = 1000;101  std::atomic<bool> m_done = false;102  HostThread m_memory_monitor_thread;103};104 105#if !defined(__APPLE__)106std::unique_ptr<MemoryMonitor> MemoryMonitor::Create(Callback callback) {107  return std::make_unique<MemoryMonitorPoll>(callback);108}109#endif110