sanitizer_allocator_test.cc revision 784935d1bbc301eaf92fd9f7d3a551eb65edcd15
1225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov//===-- sanitizer_allocator_test.cc ---------------------------------------===//
2225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov//
3225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov//                     The LLVM Compiler Infrastructure
4225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov//
5225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov// This file is distributed under the University of Illinois Open Source
6225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov// License. See LICENSE.TXT for details.
7225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov//
8225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov//===----------------------------------------------------------------------===//
9225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov//
10a3eca8192505f4796194dd24eb051019f402de99Dmitry Vyukov// This file is a part of ThreadSanitizer/AddressSanitizer runtime.
1172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany// Tests for sanitizer_allocator.h.
12225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov//
13225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov//===----------------------------------------------------------------------===//
1472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#include "sanitizer_common/sanitizer_allocator.h"
15225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov#include "sanitizer_common/sanitizer_common.h"
1672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
17225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov#include "gtest/gtest.h"
1872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
19225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov#include <stdlib.h>
2072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#include <algorithm>
2172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#include <vector>
2272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
2372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#if SANITIZER_WORDSIZE == 64
2472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanystatic const uptr kAllocatorSpace = 0x700000000000ULL;
2572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanystatic const uptr kAllocatorSize  = 0x010000000000ULL;  // 1T.
2645595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryanystatic const u64 kAddressSpaceSize = 1ULL << 47;
2772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
2872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytypedef SizeClassAllocator64<
2972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  kAllocatorSpace, kAllocatorSize, 16, DefaultSizeClassMap> Allocator64;
3072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
3172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytypedef SizeClassAllocator64<
3272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  kAllocatorSpace, kAllocatorSize, 16, CompactSizeClassMap> Allocator64Compact;
3345595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany#else
3445595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryanystatic const u64 kAddressSpaceSize = 1ULL << 32;
3572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
3672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
3745595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryanytypedef SizeClassAllocator32<
3845595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  0, kAddressSpaceSize, 16, CompactSizeClassMap> Allocator32Compact;
3945595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany
4072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate <class SizeClassMap>
4172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid TestSizeClassMap() {
4272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  typedef SizeClassMap SCMap;
4372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#if 0
4472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr i = 0; i < SCMap::kNumClasses; i++) {
4572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    printf("c%ld => %ld (%lx) cached=%ld(%ld)\n",
4672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        i, SCMap::Size(i), SCMap::Size(i), SCMap::MaxCached(i) * SCMap::Size(i),
4772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        SCMap::MaxCached(i));
4872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
4972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
5072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr c = 0; c < SCMap::kNumClasses; c++) {
5172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    uptr s = SCMap::Size(c);
5272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_EQ(SCMap::ClassID(s), c);
5372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    if (c != SCMap::kNumClasses - 1)
5472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(SCMap::ClassID(s + 1), c + 1);
5572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_EQ(SCMap::ClassID(s - 1), c);
5672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    if (c)
5772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_GT(SCMap::Size(c), SCMap::Size(c-1));
5872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
5972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  CHECK_EQ(SCMap::ClassID(SCMap::kMaxSize + 1), 0);
6072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
6172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr s = 1; s <= SCMap::kMaxSize; s++) {
6272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    uptr c = SCMap::ClassID(s);
6372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_LT(c, SCMap::kNumClasses);
6472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_GE(SCMap::Size(c), s);
6572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    if (c > 0)
6672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_LT(SCMap::Size(c-1), s);
6772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
6872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
6972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
7072166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, DefaultSizeClassMap) {
7172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassMap<DefaultSizeClassMap>();
7272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
7372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
7472166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, CompactSizeClassMap) {
7572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassMap<CompactSizeClassMap>();
7672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
7772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
7872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate <class Allocator>
7972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid TestSizeClassAllocator() {
8045595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  Allocator *a = new Allocator;
8145595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  a->Init();
8272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
8372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  static const uptr sizes[] = {1, 16, 30, 40, 100, 1000, 10000,
8472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    50000, 60000, 100000, 300000, 500000, 1000000, 2000000};
8572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
8672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  std::vector<void *> allocated;
8772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
8872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  uptr last_total_allocated = 0;
8972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < 5; i++) {
9072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    // Allocate a bunch of chunks.
9145595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany    for (uptr s = 0; s < ARRAY_SIZE(sizes); s++) {
9272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      uptr size = sizes[s];
9345595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany      if (!a->CanAllocate(size, 1)) continue;
9472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      // printf("s = %ld\n", size);
9572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      uptr n_iter = std::max((uptr)2, 1000000 / size);
9672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      for (uptr i = 0; i < n_iter; i++) {
9745595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany        void *x = a->Allocate(size, 1);
9872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        allocated.push_back(x);
9945595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany        CHECK(a->PointerIsMine(x));
10045595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany        CHECK_GE(a->GetActuallyAllocatedSize(x), size);
10145595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany        uptr class_id = a->GetSizeClass(x);
10272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        CHECK_EQ(class_id, Allocator::SizeClassMapT::ClassID(size));
10345595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany        uptr *metadata = reinterpret_cast<uptr*>(a->GetMetaData(x));
10472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        metadata[0] = reinterpret_cast<uptr>(x) + 1;
10572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        metadata[1] = 0xABCD;
10672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      }
10772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
10872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    // Deallocate all.
10972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (uptr i = 0; i < allocated.size(); i++) {
11072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      void *x = allocated[i];
11145595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany      uptr *metadata = reinterpret_cast<uptr*>(a->GetMetaData(x));
11272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(metadata[0], reinterpret_cast<uptr>(x) + 1);
11372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(metadata[1], 0xABCD);
11445595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany      a->Deallocate(x);
11572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
11672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    allocated.clear();
11745595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany    uptr total_allocated = a->TotalMemoryUsed();
11872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    if (last_total_allocated == 0)
11972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      last_total_allocated = total_allocated;
12072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_EQ(last_total_allocated, total_allocated);
12172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
12272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
12345595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  a->TestOnlyUnmap();
12445595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  delete a;
12572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
12672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
12772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#if SANITIZER_WORDSIZE == 64
12872166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64) {
12972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassAllocator<Allocator64>();
13072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
13172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
13272166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64Compact) {
13372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassAllocator<Allocator64Compact>();
13472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
13572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
13672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
13745595ba6b77b54b8212389cba6b95dc634122145Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator32Compact) {
13845595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  TestSizeClassAllocator<Allocator32Compact>();
13945595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany}
14045595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany
14172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate <class Allocator>
142784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryanyvoid SizeClassAllocatorMetadataStress() {
143784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  Allocator *a = new Allocator;
144784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  a->Init();
14572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  static volatile void *sink;
14672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
14772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const uptr kNumAllocs = 10000;
14872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  void *allocated[kNumAllocs];
14972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr i = 0; i < kNumAllocs; i++) {
15072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    uptr size = (i % 4096) + 1;
151784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany    void *x = a->Allocate(size, 1);
15272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    allocated[i] = x;
15372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
15472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Get Metadata kNumAllocs^2 times.
15572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr i = 0; i < kNumAllocs * kNumAllocs; i++) {
156784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany    sink = a->GetMetaData(allocated[i % kNumAllocs]);
15772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
15872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr i = 0; i < kNumAllocs; i++) {
159784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany    a->Deallocate(allocated[i]);
16072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
16172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
162784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  a->TestOnlyUnmap();
16372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  (void)sink;
164784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  delete a;
16572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
16672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
16772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#if SANITIZER_WORDSIZE == 64
16872166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64MetadataStress) {
169784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  SizeClassAllocatorMetadataStress<Allocator64>();
17072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
171225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov
17272166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64CompactMetadataStress) {
173784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  SizeClassAllocatorMetadataStress<Allocator64Compact>();
17472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
17572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
176784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator32CompactMetadataStress) {
177784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  SizeClassAllocatorMetadataStress<Allocator32Compact>();
178784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany}
17972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
18072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate<class Allocator>
18172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid FailInAssertionOnOOM() {
18272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  Allocator a;
18372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  a.Init();
18472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const uptr size = 1 << 20;
18572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < 1000000; i++) {
18672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    a.Allocate(size, 1);
18772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
18872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
18972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  a.TestOnlyUnmap();
19072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
19172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
19272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#if SANITIZER_WORDSIZE == 64
19372166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64Overflow) {
19472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  EXPECT_DEATH(FailInAssertionOnOOM<Allocator64>(), "Out of memory");
19572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
19672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
19772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
19872166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, LargeMmapAllocator) {
19972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  LargeMmapAllocator a;
20072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  a.Init();
20172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
20272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  static const int kNumAllocs = 100;
20372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  void *allocated[kNumAllocs];
20472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  static const uptr size = 1000;
20572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Allocate some.
20672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < kNumAllocs; i++) {
20772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    allocated[i] = a.Allocate(size, 1);
20872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
20972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Deallocate all.
21072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  CHECK_GT(a.TotalMemoryUsed(), size * kNumAllocs);
21172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < kNumAllocs; i++) {
21272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    void *p = allocated[i];
21372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK(a.PointerIsMine(p));
21472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    a.Deallocate(p);
21572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
21672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Check that non left.
21772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  CHECK_EQ(a.TotalMemoryUsed(), 0);
21872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
21972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Allocate some more, also add metadata.
22072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < kNumAllocs; i++) {
22172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    void *x = a.Allocate(size, 1);
22272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_GE(a.GetActuallyAllocatedSize(x), size);
22372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    uptr *meta = reinterpret_cast<uptr*>(a.GetMetaData(x));
22472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    *meta = i;
22572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    allocated[i] = x;
22672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
22772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  CHECK_GT(a.TotalMemoryUsed(), size * kNumAllocs);
22872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Deallocate all in reverse order.
22972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < kNumAllocs; i++) {
23072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    int idx = kNumAllocs - i - 1;
23172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    void *p = allocated[idx];
23272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    uptr *meta = reinterpret_cast<uptr*>(a.GetMetaData(p));
23372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_EQ(*meta, idx);
23472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK(a.PointerIsMine(p));
23572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    a.Deallocate(p);
23672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
23772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  CHECK_EQ(a.TotalMemoryUsed(), 0);
23872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  uptr max_alignment = SANITIZER_WORDSIZE == 64 ? (1 << 28) : (1 << 24);
23972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr alignment = 8; alignment <= max_alignment; alignment *= 2) {
24072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (int i = 0; i < kNumAllocs; i++) {
24172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      uptr size = ((i % 10) + 1) * 4096;
24272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      allocated[i] = a.Allocate(size, alignment);
24372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(0, (uptr)allocated[i] % alignment);
24472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      char *p = (char*)allocated[i];
24572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      p[0] = p[size - 1] = 0;
24672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
24772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (int i = 0; i < kNumAllocs; i++) {
24872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      a.Deallocate(allocated[i]);
24972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
25072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
25172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
25272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
25372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate
25472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany<class PrimaryAllocator, class SecondaryAllocator, class AllocatorCache>
25572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid TestCombinedAllocator() {
25672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  CombinedAllocator<PrimaryAllocator, AllocatorCache, SecondaryAllocator> a;
25772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  a.Init();
25872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
25972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  AllocatorCache cache;
26072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  cache.Init();
26172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
26272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  EXPECT_EQ(a.Allocate(&cache, -1, 1), (void*)0);
26372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  EXPECT_EQ(a.Allocate(&cache, -1, 1024), (void*)0);
26472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  EXPECT_EQ(a.Allocate(&cache, (uptr)-1 - 1024, 1), (void*)0);
26572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  EXPECT_EQ(a.Allocate(&cache, (uptr)-1 - 1024, 1024), (void*)0);
26672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  EXPECT_EQ(a.Allocate(&cache, (uptr)-1 - 1023, 1024), (void*)0);
26772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
26872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const uptr kNumAllocs = 100000;
26972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const uptr kNumIter = 10;
27072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr iter = 0; iter < kNumIter; iter++) {
27172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    std::vector<void*> allocated;
27272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (uptr i = 0; i < kNumAllocs; i++) {
27372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      uptr size = (i % (1 << 14)) + 1;
27472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      if ((i % 1024) == 0)
27572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        size = 1 << (10 + (i % 14));
27672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      void *x = a.Allocate(&cache, size, 1);
27772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      uptr *meta = reinterpret_cast<uptr*>(a.GetMetaData(x));
27872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(*meta, 0);
27972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      *meta = size;
28072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      allocated.push_back(x);
28172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
28272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
28372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    random_shuffle(allocated.begin(), allocated.end());
28472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
28572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (uptr i = 0; i < kNumAllocs; i++) {
28672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      void *x = allocated[i];
28772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      uptr *meta = reinterpret_cast<uptr*>(a.GetMetaData(x));
28872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_NE(*meta, 0);
28972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK(a.PointerIsMine(x));
29072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      *meta = 0;
29172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      a.Deallocate(&cache, x);
29272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
29372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    allocated.clear();
29472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    a.SwallowCache(&cache);
29572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
29672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  a.TestOnlyUnmap();
29772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
29872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
29972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#if SANITIZER_WORDSIZE == 64
30072166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, CombinedAllocator) {
30172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestCombinedAllocator<Allocator64,
30272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      LargeMmapAllocator,
30372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      SizeClassAllocatorLocalCache<Allocator64> > ();
30472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
30572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
30672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
30772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate <class AllocatorCache>
30872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid TestSizeClassAllocatorLocalCache() {
30972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  static THREADLOCAL AllocatorCache static_allocator_cache;
31072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  static_allocator_cache.Init();
31172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  AllocatorCache cache;
31272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  typename AllocatorCache::Allocator a;
31372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
31472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  a.Init();
31572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  cache.Init();
31672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
31772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const uptr kNumAllocs = 10000;
31872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const int kNumIter = 100;
31972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  uptr saved_total = 0;
32072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < kNumIter; i++) {
32172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    void *allocated[kNumAllocs];
32272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (uptr i = 0; i < kNumAllocs; i++) {
32372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      allocated[i] = cache.Allocate(&a, 0);
32472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
32572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (uptr i = 0; i < kNumAllocs; i++) {
32672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      cache.Deallocate(&a, 0, allocated[i]);
32772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
32872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    cache.Drain(&a);
32972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    uptr total_allocated = a.TotalMemoryUsed();
33072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    if (saved_total)
33172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(saved_total, total_allocated);
33272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    saved_total = total_allocated;
33372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
33472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
33572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  a.TestOnlyUnmap();
33672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
33772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
33872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#if SANITIZER_WORDSIZE == 64
33972166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64LocalCache) {
34072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassAllocatorLocalCache<
34172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      SizeClassAllocatorLocalCache<Allocator64> >();
34272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
34372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
344225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov
345225f53194082f475a5d21780344ff79a2a387c13Dmitry VyukovTEST(Allocator, Basic) {
346225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  char *p = (char*)InternalAlloc(10);
347225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  EXPECT_NE(p, (char*)0);
348225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  char *p2 = (char*)InternalAlloc(20);
349225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  EXPECT_NE(p2, (char*)0);
350225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  EXPECT_NE(p2, p);
351225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  InternalFree(p);
352225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  InternalFree(p2);
353225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov}
354225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov
355225f53194082f475a5d21780344ff79a2a387c13Dmitry VyukovTEST(Allocator, Stress) {
356225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  const int kCount = 1000;
357225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  char *ptrs[kCount];
358225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  unsigned rnd = 42;
359225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  for (int i = 0; i < kCount; i++) {
360225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov    uptr sz = rand_r(&rnd) % 1000;
361225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov    char *p = (char*)InternalAlloc(sz);
362225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov    EXPECT_NE(p, (char*)0);
363225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov    ptrs[i] = p;
364225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  }
365225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  for (int i = 0; i < kCount; i++) {
366225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov    InternalFree(ptrs[i]);
367225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  }
368225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov}
369225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov
3706611abe0c2737a37c1c69f0527a35bb34875221dAlexey SamsonovTEST(Allocator, ScopedBuffer) {
3716611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  const int kSize = 512;
3726611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  {
3736611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov    InternalScopedBuffer<int> int_buf(kSize);
3746611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov    EXPECT_EQ(sizeof(int) * kSize, int_buf.size());  // NOLINT
3756611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  }
3766611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  InternalScopedBuffer<char> char_buf(kSize);
3776611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  EXPECT_EQ(sizeof(char) * kSize, char_buf.size());  // NOLINT
3786611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  memset(char_buf.data(), 'c', kSize);
3796611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  for (int i = 0; i < kSize; i++) {
3806611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov    EXPECT_EQ('c', char_buf[i]);
3816611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  }
3826611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov}
383