Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Host/common/MemoryMonitor.cpp
213799 views
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-exception
6
//
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
#endif
26
27
#if defined(_WIN32)
28
#include <windows.h>
29
#endif
30
31
using namespace lldb_private;
32
33
class MemoryMonitorPoll : public MemoryMonitor {
34
public:
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
#endif
62
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
#endif
76
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
99
private:
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__)
106
std::unique_ptr<MemoryMonitor> MemoryMonitor::Create(Callback callback) {
107
return std::make_unique<MemoryMonitorPoll>(callback);
108
}
109
#endif
110
111