diff --git a/compiler-rt/lib/hwasan/hwasan_allocator.cpp b/compiler-rt/lib/hwasan/hwasan_allocator.cpp --- a/compiler-rt/lib/hwasan/hwasan_allocator.cpp +++ b/compiler-rt/lib/hwasan/hwasan_allocator.cpp @@ -677,3 +677,5 @@ } uptr __sanitizer_get_allocated_size(const void *p) { return AllocationSize(p); } + +void __sanitizer_purge_allocator() { allocator.ForceReleaseToOS(); } diff --git a/compiler-rt/test/sanitizer_common/TestCases/Linux/release_to_os_test.cpp b/compiler-rt/test/sanitizer_common/TestCases/Linux/release_to_os_test.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/Linux/release_to_os_test.cpp @@ -0,0 +1,90 @@ +// RUN: %clangxx %s -o %t +// RUN: env %tool_options=allocator_release_to_os_interval_ms=-1 %run %t + +// Not needed, no allocator. +// XFAIL: ubsan + +// FIXME: Implement +// XFAIL: lsan, msan, tsan, hwasan-aliasing + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +const size_t kPageSize = 4096; + +void sync_rss() { + char *page = + (char *)mmap((void *)&sync_rss, kPageSize, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); + // Linux kernel updates RSS counters after a set number of page faults. + for (int i = 0; i < 10000; ++i) { + page[0] = 42; + madvise(page, kPageSize, MADV_DONTNEED); + } + munmap(page, kPageSize); +} + +size_t current_rss() { + sync_rss(); + int statm_fd = open("/proc/self/statm", O_RDONLY); + assert(statm_fd >= 0); + + char buf[100]; + assert(read(statm_fd, &buf, sizeof(buf)) > 0); + size_t size, rss; + assert(sscanf(buf, "%zu %zu", &size, &rss) == 2); + + close(statm_fd); + return rss; +} + +void MallocReleaseStress() { + const size_t kNumChunks = 10000; + const size_t kAllocSize = 100; + const size_t kNumIter = 100; + uintptr_t *chunks[kNumChunks] = {0}; + std::mt19937 r; + + for (size_t iter = 0; iter < kNumIter; iter++) { + std::shuffle(chunks, chunks + kNumChunks, r); + size_t to_replace = rand() % kNumChunks; + for (size_t i = 0; i < kNumChunks; i++) { + if (chunks[i]) + assert(chunks[i][0] == (uintptr_t)chunks[i]); + if (i < to_replace) { + delete[] chunks[i]; + chunks[i] = new uintptr_t[kAllocSize]; + chunks[i][0] = (uintptr_t)chunks[i]; + } + } + } + fprintf(stderr, "before delete: %zu\n", current_rss()); + for (auto p : chunks) + delete[] p; +} + +int main(int argc, char **argv) { + // 32bit asan allocator is unsupported. + if (sizeof(void *) < 8 && __has_feature(address_sanitizer)) + return 0; + auto a = current_rss(); + MallocReleaseStress(); + auto b = current_rss(); + __sanitizer_purge_allocator(); + auto c = current_rss(); + fprintf(stderr, "a:%zu b:%zu c:%zu\n", a, b, c); + assert(a * 2 < b); + assert(c * 2 < b); +} diff --git a/compiler-rt/test/sanitizer_common/lit.common.cfg.py b/compiler-rt/test/sanitizer_common/lit.common.cfg.py --- a/compiler-rt/test/sanitizer_common/lit.common.cfg.py +++ b/compiler-rt/test/sanitizer_common/lit.common.cfg.py @@ -14,6 +14,7 @@ tool_cflags = ["-fsanitize=hwaddress", "-fuse-ld=lld"] if config.target_arch == "x86_64": tool_cflags += ["-fsanitize-hwaddress-experimental-aliasing"] + config.available_features.add("hwasan-aliasing") tool_options = "HWASAN_OPTIONS" elif config.tool_name == "tsan": tool_cflags = ["-fsanitize=thread"]