Skip to content

Commit c78c2e5

Browse files
committed
[scudo] Show the resident pages from the secondary cache.
Move the test utility to get the resident pages into linux.cpp. Add some specific tests for this function. Add displaying of resident pages from in the secondary cache when calling getStats.
1 parent 9f23877 commit c78c2e5

File tree

6 files changed

+104
-29
lines changed

6 files changed

+104
-29
lines changed

compiler-rt/lib/scudo/standalone/common.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,11 @@ u32 getThreadID();
188188
constexpr uptr MaxRandomLength = 256U;
189189
bool getRandom(void *Buffer, uptr Length, bool Blocking = false);
190190

191+
// Get the total number of resident pages for BaseAddress to BaseAddress + Size.
192+
// This function can run slowly, and is only expected to be called
193+
// from getStats functions where performance does not matter.
194+
u64 getResidentPages(uptr BaseAddress, uptr Size);
195+
191196
// Platform memory mapping functions.
192197

193198
#define MAP_ALLOWNOMEM (1U << 0)

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@ void outputRaw(const char *Buffer) {
231231

232232
void setAbortMessage(const char *Message) {}
233233

234+
u64 getResidentPages(uptr BaseAddress, uptr Size) { return 0; }
235+
234236
} // namespace scudo
235237

236238
#endif // SCUDO_FUCHSIA

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

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,34 @@ void setAbortMessage(const char *Message) {
246246
android_set_abort_message(Message);
247247
}
248248

249+
u64 getResidentPages(uptr BaseAddress, uptr Size) {
250+
unsigned char PageData[256];
251+
252+
uptr PageSize = getPageSizeCached();
253+
uptr PageSizeLog = getPageSizeLogCached();
254+
255+
// Make sure the address is page aligned.
256+
uptr CurrentAddress = BaseAddress & ~(PageSize - 1);
257+
uptr LastAddress = roundUp(BaseAddress + Size, PageSize);
258+
u64 ResidentPages = 0;
259+
while (CurrentAddress < LastAddress) {
260+
uptr Length = LastAddress - CurrentAddress;
261+
if ((Length >> PageSizeLog) > sizeof(PageData)) {
262+
Length = sizeof(PageData) << PageSizeLog;
263+
}
264+
if (mincore(reinterpret_cast<void *>(CurrentAddress), Length, PageData) ==
265+
-1)
266+
break;
267+
for (size_t I = 0; I < Length >> PageSizeLog; I++) {
268+
if (PageData[I])
269+
ResidentPages++;
270+
}
271+
CurrentAddress += Length;
272+
}
273+
274+
return ResidentPages;
275+
}
276+
249277
} // namespace scudo
250278

251279
#endif // SCUDO_LINUX

compiler-rt/lib/scudo/standalone/secondary.h

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,12 @@
99
#ifndef SCUDO_SECONDARY_H_
1010
#define SCUDO_SECONDARY_H_
1111

12+
#ifndef __STDC_FORMAT_MACROS
13+
// Ensure PRId64 macro is available
14+
#define __STDC_FORMAT_MACROS 1
15+
#endif
16+
#include <inttypes.h>
17+
1218
#include "chunk.h"
1319
#include "common.h"
1420
#include "list.h"
@@ -221,9 +227,17 @@ class MapAllocatorCache {
221227

222228
for (CachedBlock &Entry : LRUEntries) {
223229
Str->append(" StartBlockAddress: 0x%zx, EndBlockAddress: 0x%zx, "
224-
"BlockSize: %zu %s\n",
230+
"BlockSize: %zu%s",
225231
Entry.CommitBase, Entry.CommitBase + Entry.CommitSize,
226-
Entry.CommitSize, Entry.Time == 0 ? "[R]" : "");
232+
Entry.CommitSize, Entry.Time == 0 ? " [R]" : "");
233+
#if SCUDO_LINUX
234+
// getResidentPages only works on linux systems currently.
235+
Str->append(", Resident Pages: %" PRId64 "/%zu\n",
236+
getResidentPages(Entry.CommitBase, Entry.CommitSize),
237+
Entry.CommitSize / getPageSizeCached());
238+
#else
239+
Str->append("\n");
240+
#endif
227241
}
228242
}
229243

compiler-rt/lib/scudo/standalone/tests/common_test.cpp

Lines changed: 51 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,50 +21,74 @@
2121

2222
namespace scudo {
2323

24-
static void getResidentPages(void *BaseAddress, size_t TotalPages,
25-
size_t *ResidentPages) {
26-
std::vector<unsigned char> Pages(TotalPages, 0);
27-
ASSERT_EQ(
28-
0, mincore(BaseAddress, TotalPages * getPageSizeCached(), Pages.data()))
29-
<< strerror(errno);
30-
*ResidentPages = 0;
31-
for (unsigned char Value : Pages) {
32-
if (Value & 1) {
33-
++*ResidentPages;
34-
}
35-
}
24+
TEST(ScudoCommonTest, VerifyGetResidentPages) {
25+
if (!SCUDO_LINUX)
26+
GTEST_SKIP() << "Only valid on linux systems.";
27+
28+
constexpr uptr NumPages = 512;
29+
const uptr SizeBytes = NumPages * getPageSizeCached();
30+
31+
MemMapT MemMap;
32+
ASSERT_TRUE(MemMap.map(/*Addr=*/0U, SizeBytes, "ResidentMemorySize"));
33+
ASSERT_NE(MemMap.getBase(), 0U);
34+
35+
// Only android seem to properly detect when single pages are touched.
36+
#if SCUDO_ANDROID
37+
// Verify nothing should be mapped in right after the map is created.
38+
EXPECT_EQ(0U, getResidentPages(MemMap.getBase(), SizeBytes));
39+
40+
// Touch a page.
41+
u8 *Data = reinterpret_cast<u8 *>(MemMap.getBase());
42+
Data[0] = 1;
43+
EXPECT_EQ(1U, getResidentPages(MemMap.getBase(), SizeBytes));
44+
45+
// Touch a non-consective page.
46+
Data[getPageSizeCached() * 2] = 1;
47+
EXPECT_EQ(2U, getResidentPages(MemMap.getBase(), SizeBytes));
48+
49+
// Touch a page far enough that the function has to make multiple calls
50+
// to mincore.
51+
Data[getPageSizeCached() * 300] = 1;
52+
EXPECT_EQ(3U, getResidentPages(MemMap.getBase(), SizeBytes));
53+
54+
// Touch another page in the same range to make sure the second
55+
// read is working.
56+
Data[getPageSizeCached() * 400] = 1;
57+
EXPECT_EQ(4U, getResidentPages(MemMap.getBase(), SizeBytes));
58+
#endif
59+
60+
// Now write the whole thing.
61+
memset(reinterpret_cast<void *>(MemMap.getBase()), 1, SizeBytes);
62+
EXPECT_EQ(NumPages, getResidentPages(MemMap.getBase(), SizeBytes));
63+
64+
MemMap.unmap();
3665
}
3766

38-
// Fuchsia needs getResidentPages implementation.
39-
TEST(ScudoCommonTest, SKIP_ON_FUCHSIA(ResidentMemorySize)) {
40-
// Make sure to have the size of the map on a page boundary.
41-
const uptr PageSize = getPageSizeCached();
42-
const size_t NumPages = 1000;
43-
const uptr SizeBytes = NumPages * PageSize;
67+
TEST(ScudoCommonTest, VerifyReleasePagesToOS) {
68+
if (!SCUDO_LINUX)
69+
GTEST_SKIP() << "Only valid on linux systems.";
70+
71+
constexpr uptr NumPages = 1000;
72+
const uptr SizeBytes = NumPages * getPageSizeCached();
4473

4574
MemMapT MemMap;
4675
ASSERT_TRUE(MemMap.map(/*Addr=*/0U, SizeBytes, "ResidentMemorySize"));
4776
ASSERT_NE(MemMap.getBase(), 0U);
4877

4978
void *P = reinterpret_cast<void *>(MemMap.getBase());
50-
size_t ResidentPages;
51-
getResidentPages(P, NumPages, &ResidentPages);
52-
EXPECT_EQ(0U, ResidentPages);
79+
EXPECT_EQ(0U, getResidentPages(MemMap.getBase(), SizeBytes));
5380

5481
// Make the entire map resident.
5582
memset(P, 1, SizeBytes);
56-
getResidentPages(P, NumPages, &ResidentPages);
57-
EXPECT_EQ(NumPages, ResidentPages);
83+
EXPECT_EQ(NumPages, getResidentPages(MemMap.getBase(), SizeBytes));
5884

5985
// Should release the memory to the kernel immediately.
6086
MemMap.releasePagesToOS(MemMap.getBase(), SizeBytes);
61-
getResidentPages(P, NumPages, &ResidentPages);
62-
EXPECT_EQ(0U, ResidentPages);
87+
EXPECT_EQ(0U, getResidentPages(MemMap.getBase(), SizeBytes));
6388

6489
// Make the entire map resident again.
6590
memset(P, 1, SizeBytes);
66-
getResidentPages(P, NumPages, &ResidentPages);
67-
EXPECT_EQ(NumPages, ResidentPages);
91+
EXPECT_EQ(NumPages, getResidentPages(MemMap.getBase(), SizeBytes));
6892

6993
MemMap.unmap();
7094
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ void outputRaw(const char *Buffer) { printf("%s", Buffer); }
113113

114114
void setAbortMessage(UNUSED const char *Message) {}
115115

116+
u64 getResidentPages(UNUSED uptr BaseAddress, UNUSED uptr Size) { return 0; }
117+
116118
} // namespace scudo
117119

118120
#endif // SCUDO_TRUSTY

0 commit comments

Comments
 (0)