Skip to content

Commit 045a620

Browse files
Release the shadow memory used by the mmap range at munmap
When an application does a lot of pairs of mmap and munmap, if we did not release shadoe memory used by mmap addresses, this would increase memory usage. Reviewed-by: morehouse Differential Revision: https://reviews.llvm.org/D88686
1 parent 11622d0 commit 045a620

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

compiler-rt/lib/dfsan/dfsan_interceptors.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,25 @@ INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags,
4646
return res;
4747
}
4848

49+
INTERCEPTOR(int, munmap, void *addr, SIZE_T length) {
50+
int res = REAL(munmap)(addr, length);
51+
if (res != -1) {
52+
uptr beg_shadow_addr = (uptr)__dfsan::shadow_for(addr);
53+
void *end_addr =
54+
(void *)((uptr)addr + RoundUpTo(length, GetPageSizeCached()));
55+
uptr end_shadow_addr = (uptr)__dfsan::shadow_for(end_addr);
56+
ReleaseMemoryPagesToOS(beg_shadow_addr, end_shadow_addr);
57+
}
58+
return res;
59+
}
60+
4961
namespace __dfsan {
5062
void InitializeInterceptors() {
5163
CHECK(!interceptors_initialized);
5264

5365
INTERCEPT_FUNCTION(mmap);
5466
INTERCEPT_FUNCTION(mmap64);
67+
INTERCEPT_FUNCTION(munmap);
5568

5669
interceptors_initialized = true;
5770
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// RUN: %clang_dfsan %s -o %t && %run %t
2+
3+
#include <assert.h>
4+
#include <sanitizer/dfsan_interface.h>
5+
#include <stdbool.h>
6+
#include <stdio.h>
7+
#include <string.h>
8+
#include <sys/mman.h>
9+
#include <unistd.h>
10+
11+
size_t get_rss_kb() {
12+
long rss = 0L;
13+
FILE *f = NULL;
14+
assert((f = fopen("/proc/self/statm", "r")));
15+
assert(fscanf(f, "%*s%ld", &rss) == 1);
16+
fclose(f);
17+
return ((size_t)rss * (size_t)sysconf(_SC_PAGESIZE)) >> 10;
18+
}
19+
20+
int main(int argc, char **argv) {
21+
const size_t map_size = 100 << 20;
22+
size_t before = get_rss_kb();
23+
24+
char *p = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
25+
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
26+
const dfsan_label label = dfsan_create_label("l", 0);
27+
char val = 0xff;
28+
dfsan_set_label(label, &val, sizeof(val));
29+
memset(p, val, map_size);
30+
size_t after_mmap = get_rss_kb();
31+
32+
munmap(p, map_size);
33+
size_t after_munmap = get_rss_kb();
34+
35+
fprintf(stderr, "RSS at start: %td, after mmap: %td, after mumap: %td\n",
36+
before, after_mmap, after_munmap);
37+
38+
// The memory after mmap increases 3 times of map_size because the overhead of
39+
// shadow memory is 2x.
40+
const size_t mmap_cost_kb = 3 * (map_size >> 10);
41+
assert(after_mmap >= before + mmap_cost_kb);
42+
// OS does not release memory to the same level as the start of the program.
43+
// The assert checks the memory after munmap up to a delta.
44+
const size_t delta = 5000;
45+
assert(after_munmap + mmap_cost_kb <= after_mmap + delta);
46+
return 0;
47+
}

0 commit comments

Comments
 (0)