// RUN: %clangxx %s -o %t // RUN: env %tool_options=allocator_release_to_os_interval_ms=-1 %run %t // Temporarily disable test // UNSUPPORTED: tsan // UNSUPPORTED: target={{(powerpc64|loongarch64).*}} // Not needed, no allocator. // UNSUPPORTED: ubsan // FIXME: This mode uses 32bit allocator without purge. // UNSUPPORTED: hwasan-aliasing // Page size is hardcoded below, but test still fails even if not hardcoded. // REQUIRES: page-size-4096 #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; } size_t 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; return kNumChunks * kAllocSize * sizeof(uintptr_t); } int main(int argc, char **argv) { // 32bit asan allocator is unsupported. if (sizeof(void *) < 8) return 0; auto a = current_rss(); auto total = MallocReleaseStress() >> 10; auto b = current_rss(); __sanitizer_purge_allocator(); auto c = current_rss(); fprintf(stderr, "a:%zu b:%zu c:%zu total:%zu\n", a, b, c, total); assert(a + total / 8 < b); assert(c + total / 8 < b); }