14#include "llvm/ADT/ScopeExit.h"
15#include "llvm/Support/Error.h"
23#include <sys/eventfd.h>
40 explicit MemoryMonitorLinux(Callback callback)
41 : MemoryMonitor(std::move(callback)),
42 m_stop_fd(::eventfd(0, EFD_NONBLOCK)) {}
44 ~MemoryMonitorLinux() {
45 if (m_memory_monitor_thread.IsJoinable())
46 m_memory_monitor_thread.Join(
nullptr);
51 void Start()
override {
55 llvm::errorCodeToError(llvm::errnoAsErrorCode()),
56 "failed to create stop file descriptor for memory monitor: {0}");
60 llvm::Expected<HostThread> memory_monitor_thread =
63 if (memory_monitor_thread) {
64 m_memory_monitor_thread = *memory_monitor_thread;
67 "failed to launch host thread: {0}");
71 void Stop()
override {
72 if (m_memory_monitor_thread.IsJoinable()) {
74 ::eventfd_write(m_stop_fd, 1);
75 m_memory_monitor_thread.Join(
nullptr);
81 constexpr size_t pressure_idx = 0;
82 constexpr size_t stop_idx = 1;
83 constexpr size_t fd_count = 2;
84 std::array<pollfd, fd_count> pfds{};
87 pfds[stop_idx].fd = m_stop_fd;
88 pfds[stop_idx].events = POLLIN;
91 pfds[pressure_idx].fd =
92 ::open(
"/proc/pressure/memory", O_RDWR |
O_NONBLOCK);
93 if (pfds[pressure_idx].fd < 0)
95 pfds[pressure_idx].events = POLLPRI;
97 llvm::scope_exit cleanup([&]() { ::close(pfds[pressure_idx].fd); });
100 constexpr llvm::StringRef trigger =
"some 50000 2000000";
101 if (::write(pfds[pressure_idx].fd, trigger.data(), trigger.size() + 1) < 0)
105 constexpr int timeout_infinite = -1;
106 const int n = ::poll(pfds.data(), pfds.size(), timeout_infinite);
109 if (pfds[stop_idx].revents & (POLLIN | POLLERR))
112 if (pfds[pressure_idx].revents & POLLERR)
114 if (pfds[pressure_idx].revents & POLLPRI)
121 HostThread m_memory_monitor_thread;
130 HANDLE low_memory_notification =
131 CreateMemoryResourceNotification(LowMemoryResourceNotification);
132 if (!low_memory_notification)
136 if (WaitForSingleObject(low_memory_notification, g_timeout) ==
144 void Start()
override {
145 llvm::Expected<HostThread> memory_monitor_thread =
148 if (memory_monitor_thread) {
149 m_memory_monitor_thread = *memory_monitor_thread;
152 "failed to launch host thread: {0}");
156 void Stop()
override {
157 if (m_memory_monitor_thread.IsJoinable()) {
159 m_memory_monitor_thread.Join(
nullptr);
164 static constexpr uint32_t g_timeout = 1000;
165 std::atomic<bool> m_done =
false;
166 HostThread m_memory_monitor_thread;
170#if !defined(__APPLE__)
172#if defined(__linux__)
173 return std::make_unique<MemoryMonitorLinux>(std::move(callback));
175 return std::make_unique<MemoryMonitorWindows>(std::move(callback));
static lldb::thread_result_t MonitorThread(const Host::MonitorChildProcessCallback &callback, HANDLE process_handle)
#define LLDB_LOG_ERROR(log, error,...)
MemoryMonitor(Callback callback)
static std::unique_ptr< MemoryMonitor > Create(Callback callback)
std::function< void()> Callback
static llvm::Expected< HostThread > LaunchThread(llvm::StringRef name, std::function< lldb::thread_result_t()> thread_function, size_t min_stack_byte_size=0)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.