Skip to content

Commit 9209e10

Browse files
committed
Use NativeThread and attempt a Windows implementation
1 parent 0563235 commit 9209e10

File tree

1 file changed

+68
-38
lines changed

1 file changed

+68
-38
lines changed

lldb/source/Host/common/MemoryMonitor.cpp

Lines changed: 68 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,74 +7,104 @@
77
//===----------------------------------------------------------------------===//
88

99
#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"
1014
#include "llvm/ADT/ScopeExit.h"
15+
#include "llvm/Support/Error.h"
1116
#include <atomic>
17+
#include <cstddef>
1218
#include <cstdio>
1319
#include <cstring>
14-
#include <thread>
1520

1621
#if defined(__linux__)
1722
#include <fcntl.h>
1823
#include <poll.h>
1924
#include <unistd.h>
2025
#endif
2126

27+
#if defined(_WIN32)
28+
#include <memoryapi.h>
29+
#include <synchapi.h>
30+
#endif
31+
2232
using namespace lldb_private;
2333

34+
class MemoryMonitorPoll : public MemoryMonitor {
35+
public:
36+
using MemoryMonitor::MemoryMonitor;
37+
38+
lldb::thread_result_t MonitorThread() {
2439
#if defined(__linux__)
25-
static void MonitorThread(std::atomic<bool> &done,
26-
MemoryMonitor::Callback callback) {
27-
struct pollfd fds;
28-
fds.fd = open("/proc/pressure/memory", O_RDWR | O_NONBLOCK);
29-
if (fds.fd < 0)
30-
return;
31-
fds.events = POLLPRI;
32-
33-
auto cleanup = llvm::make_scope_exit([&]() { close(fds.fd); });
34-
35-
// Detect a 50ms stall in a 2 second time window.
36-
const char trig[] = "some 50000 2000000";
37-
if (write(fds.fd, trig, strlen(trig) + 1) < 0)
38-
return;
39-
40-
while (!done) {
41-
int n = poll(&fds, 1, 1000);
42-
if (n > 0) {
43-
if (fds.revents & POLLERR)
44-
return;
45-
if (fds.revents & POLLPRI)
46-
callback();
40+
struct pollfd fds;
41+
fds.fd = open("/proc/pressure/memory", O_RDWR | O_NONBLOCK);
42+
if (fds.fd < 0)
43+
return {};
44+
fds.events = POLLPRI;
45+
46+
auto cleanup = llvm::make_scope_exit([&]() { close(fds.fd); });
47+
48+
// Detect a 50ms stall in a 2 second time window.
49+
const char trig[] = "some 50000 2000000";
50+
if (write(fds.fd, trig, strlen(trig) + 1) < 0)
51+
return {};
52+
53+
while (!m_done) {
54+
int n = poll(&fds, 1, g_timeout);
55+
if (n > 0) {
56+
if (fds.revents & POLLERR)
57+
return {};
58+
if (fds.revents & POLLPRI)
59+
m_callback();
60+
}
4761
}
48-
}
49-
}
62+
#endif
5063

51-
class MemoryMonitorLinux : public MemoryMonitor {
52-
public:
53-
using MemoryMonitor::MemoryMonitor;
64+
#if defined(_WIN32)
65+
HANDLE low_memory_notification =
66+
CreateMemoryResourceNotification(LowMemoryResourceNotification);
67+
if (!low_memory_notification)
68+
return {};
69+
70+
while (!m_done) {
71+
if (WaitForSingleObject(low_memory_notification, g_timeout) ==
72+
WAIT_OBJECT_0) {
73+
m_callback();
74+
}
75+
}
76+
#endif
77+
78+
return {};
79+
}
5480

5581
void Start() override {
56-
m_memory_pressure_thread =
57-
std::thread(MonitorThread, std::ref(m_done), m_callback);
82+
llvm::Expected<HostThread> memory_monitor_thread =
83+
ThreadLauncher::LaunchThread("lldb.debugger.memory-monitor",
84+
[this] { return MonitorThread(); });
85+
if (memory_monitor_thread) {
86+
m_memory_monitor_thread = *memory_monitor_thread;
87+
} else {
88+
LLDB_LOG_ERROR(GetLog(LLDBLog::Host), memory_monitor_thread.takeError(),
89+
"failed to launch host thread: {0}");
90+
}
5891
}
5992

6093
void Stop() override {
61-
if (m_memory_pressure_thread.joinable()) {
94+
if (m_memory_monitor_thread.IsJoinable()) {
6295
m_done = true;
63-
m_memory_pressure_thread.join();
96+
m_memory_monitor_thread.Join(nullptr);
6497
}
6598
}
6699

67100
private:
101+
static constexpr uint32_t g_timeout = 1000;
68102
std::atomic<bool> m_done = false;
69-
std::thread m_memory_pressure_thread;
103+
HostThread m_memory_monitor_thread;
70104
};
71-
#endif
72105

73106
#if !defined(__APPLE__)
74107
std::unique_ptr<MemoryMonitor> MemoryMonitor::Create(Callback callback) {
75-
#if defined(__linux__)
76-
return std::make_unique<MemoryMonitorLinux>(callback);
77-
#endif
78-
return nullptr;
108+
return std::make_unique<MemoryMonitorPoll>(callback);
79109
}
80110
#endif

0 commit comments

Comments
 (0)