1// RUN: %clangxx %s -o %t
2// RUN: env %tool_options=allocator_release_to_os_interval_ms=-1 %run %t
3
4// Temporarily disable test
5// UNSUPPORTED: tsan
6// UNSUPPORTED: target={{(powerpc64|loongarch64).*}}
7
8// Not needed, no allocator.
9// UNSUPPORTED: ubsan
10
11// FIXME: This mode uses 32bit allocator without purge.
12// UNSUPPORTED: hwasan-aliasing
13
14#include <algorithm>
15#include <assert.h>
16#include <fcntl.h>
17#include <random>
18#include <stdint.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <sys/mman.h>
23#include <sys/stat.h>
24#include <sys/types.h>
25#include <unistd.h>
26
27#include <sanitizer/allocator_interface.h>
28
29const size_t kPageSize = 4096;
30
31void sync_rss() {
32 char *page =
33 (char *)mmap(addr: (void *)&sync_rss, len: kPageSize, PROT_READ | PROT_WRITE,
34 MAP_PRIVATE | MAP_ANONYMOUS, fd: 0, offset: 0);
35 // Linux kernel updates RSS counters after a set number of page faults.
36 for (int i = 0; i < 10000; ++i) {
37 page[0] = 42;
38 madvise(addr: page, len: kPageSize, MADV_DONTNEED);
39 }
40 munmap(addr: page, len: kPageSize);
41}
42
43size_t current_rss() {
44 sync_rss();
45 int statm_fd = open(file: "/proc/self/statm", O_RDONLY);
46 assert(statm_fd >= 0);
47
48 char buf[100];
49 assert(read(statm_fd, &buf, sizeof(buf)) > 0);
50 size_t size, rss;
51 assert(sscanf(buf, "%zu %zu", &size, &rss) == 2);
52
53 close(fd: statm_fd);
54 return rss;
55}
56
57size_t MallocReleaseStress() {
58 const size_t kNumChunks = 10000;
59 const size_t kAllocSize = 100;
60 const size_t kNumIter = 100;
61 uintptr_t *chunks[kNumChunks] = {0};
62 std::mt19937 r;
63
64 for (size_t iter = 0; iter < kNumIter; iter++) {
65 std::shuffle(first: chunks, last: chunks + kNumChunks, g&: r);
66 size_t to_replace = rand() % kNumChunks;
67 for (size_t i = 0; i < kNumChunks; i++) {
68 if (chunks[i])
69 assert(chunks[i][0] == (uintptr_t)chunks[i]);
70 if (i < to_replace) {
71 delete[] chunks[i];
72 chunks[i] = new uintptr_t[kAllocSize];
73 chunks[i][0] = (uintptr_t)chunks[i];
74 }
75 }
76 }
77 fprintf(stderr, format: "before delete: %zu\n", current_rss());
78 for (auto p : chunks)
79 delete[] p;
80 return kNumChunks * kAllocSize * sizeof(uintptr_t);
81}
82
83int main(int argc, char **argv) {
84 // 32bit asan allocator is unsupported.
85 if (sizeof(void *) < 8)
86 return 0;
87 auto a = current_rss();
88 auto total = MallocReleaseStress() >> 10;
89 auto b = current_rss();
90 __sanitizer_purge_allocator();
91 auto c = current_rss();
92 fprintf(stderr, format: "a:%zu b:%zu c:%zu total:%zu\n", a, b, c, total);
93 assert(a + total / 8 < b);
94 assert(c + total / 8 < b);
95}
96

source code of compiler-rt/test/sanitizer_common/TestCases/Linux/release_to_os_test.cpp