Skip to content

Commit d423509

Browse files
committed
[scudo] Check if MADV_DONTNEED zeroes memory
QEMU just ignores MADV_DONTNEED https://github.com/qemu/qemu/blob/b1cffefa1b163bce9aebc3416f562c1d3886eeaa/linux-user/syscall.c#L11941 Depends on D100998. Differential Revision: https://reviews.llvm.org/D101031
1 parent e250829 commit d423509

File tree

1 file changed

+32
-0
lines changed

1 file changed

+32
-0
lines changed

compiler-rt/lib/scudo/standalone/linux.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#if SCUDO_LINUX
1212

13+
#include "atomic_helpers.h"
1314
#include "common.h"
1415
#include "linux.h"
1516
#include "mutex.h"
@@ -89,9 +90,40 @@ void setMemoryPermission(uptr Addr, uptr Size, uptr Flags,
8990
dieOnMapUnmapError();
9091
}
9192

93+
static bool madviseNeedsMemset() {
94+
uptr Size = getPageSizeCached();
95+
char *P = (char *)mmap(0, Size, PROT_READ | PROT_WRITE,
96+
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
97+
if (!P)
98+
dieOnMapUnmapError(errno == ENOMEM);
99+
*P = -1;
100+
while (madvise(P, Size, MADV_DONTNEED) == -1 && errno == EAGAIN) {
101+
}
102+
bool R = (*P != 0);
103+
if (munmap(P, Size) != 0)
104+
dieOnMapUnmapError();
105+
return R;
106+
}
107+
108+
static bool madviseNeedsMemsetCached() {
109+
static atomic_u8 Cache;
110+
enum State : u8 { Unknown = 0, Yes = 1, No = 2 };
111+
State NeedsMemset = static_cast<State>(atomic_load_relaxed(&Cache));
112+
if (NeedsMemset == Unknown) {
113+
NeedsMemset = madviseNeedsMemset() ? Yes : No;
114+
atomic_store_relaxed(&Cache, NeedsMemset);
115+
}
116+
return NeedsMemset == Yes;
117+
}
118+
92119
void releasePagesToOS(uptr BaseAddress, uptr Offset, uptr Size,
93120
UNUSED MapPlatformData *Data) {
94121
void *Addr = reinterpret_cast<void *>(BaseAddress + Offset);
122+
if (madviseNeedsMemsetCached()) {
123+
// Workaround for QEMU-user ignoring MADV_DONTNEED.
124+
// https://github.com/qemu/qemu/blob/b1cffefa1b163bce9aebc3416f562c1d3886eeaa/linux-user/syscall.c#L11941
125+
memset(Addr, 0, Size);
126+
}
95127
while (madvise(Addr, Size, MADV_DONTNEED) == -1 && errno == EAGAIN) {
96128
}
97129
}

0 commit comments

Comments
 (0)