|
11 | 11 |
|
12 | 12 | #include "common.h"
|
13 | 13 | #include "mem_map.h"
|
| 14 | + |
| 15 | +#include <errno.h> |
| 16 | +#include <string.h> |
| 17 | +#include <sys/mman.h> |
| 18 | + |
14 | 19 | #include <algorithm>
|
15 |
| -#include <fstream> |
| 20 | +#include <vector> |
16 | 21 |
|
17 | 22 | namespace scudo {
|
18 | 23 |
|
19 |
| -static uptr getResidentMemorySize() { |
20 |
| - if (!SCUDO_LINUX) |
21 |
| - UNREACHABLE("Not implemented!"); |
22 |
| - uptr Size; |
23 |
| - uptr Resident; |
24 |
| - std::ifstream IFS("/proc/self/statm"); |
25 |
| - IFS >> Size; |
26 |
| - IFS >> Resident; |
27 |
| - return Resident * getPageSizeCached(); |
| 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 | + } |
28 | 36 | }
|
29 | 37 |
|
30 |
| -// Fuchsia needs getResidentMemorySize implementation. |
| 38 | +// Fuchsia needs getResidentPages implementation. |
31 | 39 | TEST(ScudoCommonTest, SKIP_ON_FUCHSIA(ResidentMemorySize)) {
|
32 |
| - uptr OnStart = getResidentMemorySize(); |
33 |
| - EXPECT_GT(OnStart, 0UL); |
34 |
| - |
35 |
| - const uptr Size = 1ull << 30; |
36 |
| - const uptr Threshold = Size >> 3; |
| 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; |
37 | 44 |
|
38 | 45 | MemMapT MemMap;
|
39 |
| - ASSERT_TRUE(MemMap.map(/*Addr=*/0U, Size, "ResidentMemorySize")); |
| 46 | + ASSERT_TRUE(MemMap.map(/*Addr=*/0U, SizeBytes, "ResidentMemorySize")); |
40 | 47 | ASSERT_NE(MemMap.getBase(), 0U);
|
41 |
| - void *P = reinterpret_cast<void *>(MemMap.getBase()); |
42 |
| - EXPECT_LT(getResidentMemorySize(), OnStart + Threshold); |
43 |
| - |
44 |
| - memset(P, 1, Size); |
45 |
| - EXPECT_GT(getResidentMemorySize(), OnStart + Size - Threshold); |
46 |
| - |
47 |
| - MemMap.releasePagesToOS(MemMap.getBase(), Size); |
48 |
| - EXPECT_LT(getResidentMemorySize(), OnStart + Threshold); |
49 | 48 |
|
50 |
| - memset(P, 1, Size); |
51 |
| - EXPECT_GT(getResidentMemorySize(), OnStart + Size - Threshold); |
| 49 | + void *P = reinterpret_cast<void *>(MemMap.getBase()); |
| 50 | + size_t ResidentPages; |
| 51 | + getResidentPages(P, NumPages, &ResidentPages); |
| 52 | + EXPECT_EQ(0U, ResidentPages); |
| 53 | + |
| 54 | + // Make the entire map resident. |
| 55 | + memset(P, 1, SizeBytes); |
| 56 | + getResidentPages(P, NumPages, &ResidentPages); |
| 57 | + EXPECT_EQ(NumPages, ResidentPages); |
| 58 | + |
| 59 | + // Should release the memory to the kernel immediately. |
| 60 | + MemMap.releasePagesToOS(MemMap.getBase(), SizeBytes); |
| 61 | + getResidentPages(P, NumPages, &ResidentPages); |
| 62 | + EXPECT_EQ(0U, ResidentPages); |
| 63 | + |
| 64 | + // Make the entire map resident again. |
| 65 | + memset(P, 1, SizeBytes); |
| 66 | + getResidentPages(P, NumPages, &ResidentPages); |
| 67 | + EXPECT_EQ(NumPages, ResidentPages); |
52 | 68 |
|
53 | 69 | MemMap.unmap();
|
54 | 70 | }
|
|
0 commit comments