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