sanitizer_allocator_test.cc revision 68acb909db275a9d4fb16b37fab4c42b72671abb
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>
209fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany#include <pthread.h>
2172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#include <algorithm>
2272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#include <vector>
2372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
2468902f431172d101f3c6322d96a99d705a37ad95Dmitry Vyukov// Too slow for debug build
25b6bb60b0fa39efee537cc34bc200edc976df0bc4Dmitry Vyukov#if TSAN_DEBUG == 0
2668902f431172d101f3c6322d96a99d705a37ad95Dmitry Vyukov
2772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#if SANITIZER_WORDSIZE == 64
2872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanystatic const uptr kAllocatorSpace = 0x700000000000ULL;
2972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanystatic const uptr kAllocatorSize  = 0x010000000000ULL;  // 1T.
3045595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryanystatic const u64 kAddressSpaceSize = 1ULL << 47;
3172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
3272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytypedef SizeClassAllocator64<
3372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  kAllocatorSpace, kAllocatorSize, 16, DefaultSizeClassMap> Allocator64;
3472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
3572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytypedef SizeClassAllocator64<
3672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  kAllocatorSpace, kAllocatorSize, 16, CompactSizeClassMap> Allocator64Compact;
3745595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany#else
3845595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryanystatic const u64 kAddressSpaceSize = 1ULL << 32;
3972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
4072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
4145595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryanytypedef SizeClassAllocator32<
4245595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  0, kAddressSpaceSize, 16, CompactSizeClassMap> Allocator32Compact;
4345595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany
4472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate <class SizeClassMap>
4572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid TestSizeClassMap() {
4672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  typedef SizeClassMap SCMap;
4772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#if 0
4872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr i = 0; i < SCMap::kNumClasses; i++) {
4972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    printf("c%ld => %ld (%lx) cached=%ld(%ld)\n",
5072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        i, SCMap::Size(i), SCMap::Size(i), SCMap::MaxCached(i) * SCMap::Size(i),
5172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        SCMap::MaxCached(i));
5272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
5372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
5472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr c = 0; c < SCMap::kNumClasses; c++) {
5572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    uptr s = SCMap::Size(c);
5672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_EQ(SCMap::ClassID(s), c);
5772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    if (c != SCMap::kNumClasses - 1)
5872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(SCMap::ClassID(s + 1), c + 1);
5972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_EQ(SCMap::ClassID(s - 1), c);
6072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    if (c)
6172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_GT(SCMap::Size(c), SCMap::Size(c-1));
6272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
6372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  CHECK_EQ(SCMap::ClassID(SCMap::kMaxSize + 1), 0);
6472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
6572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr s = 1; s <= SCMap::kMaxSize; s++) {
6672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    uptr c = SCMap::ClassID(s);
6772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_LT(c, SCMap::kNumClasses);
6872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_GE(SCMap::Size(c), s);
6972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    if (c > 0)
7072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_LT(SCMap::Size(c-1), s);
7172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
7272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
7372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
7472166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, DefaultSizeClassMap) {
7572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassMap<DefaultSizeClassMap>();
7672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
7772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
7872166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, CompactSizeClassMap) {
7972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassMap<CompactSizeClassMap>();
8072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
8172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
8272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate <class Allocator>
8372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid TestSizeClassAllocator() {
8445595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  Allocator *a = new Allocator;
8545595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  a->Init();
8672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
8772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  static const uptr sizes[] = {1, 16, 30, 40, 100, 1000, 10000,
8872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    50000, 60000, 100000, 300000, 500000, 1000000, 2000000};
8972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
9072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  std::vector<void *> allocated;
9172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
9272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  uptr last_total_allocated = 0;
9372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < 5; i++) {
9472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    // Allocate a bunch of chunks.
9545595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany    for (uptr s = 0; s < ARRAY_SIZE(sizes); s++) {
9672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      uptr size = sizes[s];
9745595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany      if (!a->CanAllocate(size, 1)) continue;
9872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      // printf("s = %ld\n", size);
9972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      uptr n_iter = std::max((uptr)2, 1000000 / size);
10072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      for (uptr i = 0; i < n_iter; i++) {
10145595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany        void *x = a->Allocate(size, 1);
10272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        allocated.push_back(x);
1038a41bdc963afdf3c2e14aad64a7cd3291fefd8cfKostya Serebryany        CHECK_EQ(x, a->GetBlockBegin(x));
1048a41bdc963afdf3c2e14aad64a7cd3291fefd8cfKostya Serebryany        CHECK_EQ(x, a->GetBlockBegin((char*)x + size - 1));
10545595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany        CHECK(a->PointerIsMine(x));
10645595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany        CHECK_GE(a->GetActuallyAllocatedSize(x), size);
10745595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany        uptr class_id = a->GetSizeClass(x);
10872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        CHECK_EQ(class_id, Allocator::SizeClassMapT::ClassID(size));
10945595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany        uptr *metadata = reinterpret_cast<uptr*>(a->GetMetaData(x));
11072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        metadata[0] = reinterpret_cast<uptr>(x) + 1;
11172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        metadata[1] = 0xABCD;
11272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      }
11372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
11472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    // Deallocate all.
11572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (uptr i = 0; i < allocated.size(); i++) {
11672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      void *x = allocated[i];
11745595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany      uptr *metadata = reinterpret_cast<uptr*>(a->GetMetaData(x));
11872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(metadata[0], reinterpret_cast<uptr>(x) + 1);
11972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(metadata[1], 0xABCD);
12045595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany      a->Deallocate(x);
12172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
12272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    allocated.clear();
12345595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany    uptr total_allocated = a->TotalMemoryUsed();
12472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    if (last_total_allocated == 0)
12572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      last_total_allocated = total_allocated;
12672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_EQ(last_total_allocated, total_allocated);
12772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
12872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
12945595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  a->TestOnlyUnmap();
13045595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  delete a;
13172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
13272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
13372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#if SANITIZER_WORDSIZE == 64
13472166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64) {
13572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassAllocator<Allocator64>();
13672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
13772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
13872166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64Compact) {
13972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassAllocator<Allocator64Compact>();
14072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
14172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
14272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
14345595ba6b77b54b8212389cba6b95dc634122145Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator32Compact) {
14445595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  TestSizeClassAllocator<Allocator32Compact>();
14545595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany}
14645595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany
14772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate <class Allocator>
148784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryanyvoid SizeClassAllocatorMetadataStress() {
149784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  Allocator *a = new Allocator;
150784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  a->Init();
15172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  static volatile void *sink;
15272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
15372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const uptr kNumAllocs = 10000;
15472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  void *allocated[kNumAllocs];
15572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr i = 0; i < kNumAllocs; i++) {
15672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    uptr size = (i % 4096) + 1;
157784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany    void *x = a->Allocate(size, 1);
15872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    allocated[i] = x;
15972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
16072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Get Metadata kNumAllocs^2 times.
16172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr i = 0; i < kNumAllocs * kNumAllocs; i++) {
162784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany    sink = a->GetMetaData(allocated[i % kNumAllocs]);
16372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
16472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr i = 0; i < kNumAllocs; i++) {
165784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany    a->Deallocate(allocated[i]);
16672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
16772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
168784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  a->TestOnlyUnmap();
16972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  (void)sink;
170784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  delete a;
17172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
17272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
17372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#if SANITIZER_WORDSIZE == 64
17472166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64MetadataStress) {
175784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  SizeClassAllocatorMetadataStress<Allocator64>();
17672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
177225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov
17872166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64CompactMetadataStress) {
179784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  SizeClassAllocatorMetadataStress<Allocator64Compact>();
18072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
18172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
182784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator32CompactMetadataStress) {
183784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  SizeClassAllocatorMetadataStress<Allocator32Compact>();
184784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany}
18572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
186214621f7663896987dc509561c762460226c68c2Kostya Serebryanystruct TestMapUnmapCallback {
187214621f7663896987dc509561c762460226c68c2Kostya Serebryany  static int map_count, unmap_count;
188214621f7663896987dc509561c762460226c68c2Kostya Serebryany  void OnMap(uptr p, uptr size) const { map_count++; }
189214621f7663896987dc509561c762460226c68c2Kostya Serebryany  void OnUnmap(uptr p, uptr size) const { unmap_count++; }
190214621f7663896987dc509561c762460226c68c2Kostya Serebryany};
191214621f7663896987dc509561c762460226c68c2Kostya Serebryanyint TestMapUnmapCallback::map_count;
192214621f7663896987dc509561c762460226c68c2Kostya Serebryanyint TestMapUnmapCallback::unmap_count;
193214621f7663896987dc509561c762460226c68c2Kostya Serebryany
194214621f7663896987dc509561c762460226c68c2Kostya Serebryany#if SANITIZER_WORDSIZE == 64
195214621f7663896987dc509561c762460226c68c2Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64MapUnmapCallback) {
196214621f7663896987dc509561c762460226c68c2Kostya Serebryany  TestMapUnmapCallback::map_count = 0;
197214621f7663896987dc509561c762460226c68c2Kostya Serebryany  TestMapUnmapCallback::unmap_count = 0;
198214621f7663896987dc509561c762460226c68c2Kostya Serebryany  typedef SizeClassAllocator64<
199214621f7663896987dc509561c762460226c68c2Kostya Serebryany      kAllocatorSpace, kAllocatorSize, 16, DefaultSizeClassMap,
200214621f7663896987dc509561c762460226c68c2Kostya Serebryany      TestMapUnmapCallback> Allocator64WithCallBack;
201214621f7663896987dc509561c762460226c68c2Kostya Serebryany  Allocator64WithCallBack *a = new Allocator64WithCallBack;
202214621f7663896987dc509561c762460226c68c2Kostya Serebryany  a->Init();
203214621f7663896987dc509561c762460226c68c2Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::map_count, 1);  // Allocator state.
204567ad078d73babb2c8addfbebb1ddd6cd0085c53Kostya Serebryany  a->Allocate(100, 1);
205567ad078d73babb2c8addfbebb1ddd6cd0085c53Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::map_count, 3);  // State + alloc + metadata.
206214621f7663896987dc509561c762460226c68c2Kostya Serebryany  a->TestOnlyUnmap();
207214621f7663896987dc509561c762460226c68c2Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::unmap_count, 1);  // The whole thing.
208214621f7663896987dc509561c762460226c68c2Kostya Serebryany  delete a;
209214621f7663896987dc509561c762460226c68c2Kostya Serebryany}
210214621f7663896987dc509561c762460226c68c2Kostya Serebryany#endif
211214621f7663896987dc509561c762460226c68c2Kostya Serebryany
212214621f7663896987dc509561c762460226c68c2Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator32MapUnmapCallback) {
213214621f7663896987dc509561c762460226c68c2Kostya Serebryany  TestMapUnmapCallback::map_count = 0;
214214621f7663896987dc509561c762460226c68c2Kostya Serebryany  TestMapUnmapCallback::unmap_count = 0;
215214621f7663896987dc509561c762460226c68c2Kostya Serebryany  typedef SizeClassAllocator32<
216214621f7663896987dc509561c762460226c68c2Kostya Serebryany      0, kAddressSpaceSize, 16, CompactSizeClassMap,
217214621f7663896987dc509561c762460226c68c2Kostya Serebryany      TestMapUnmapCallback> Allocator32WithCallBack;
218214621f7663896987dc509561c762460226c68c2Kostya Serebryany  Allocator32WithCallBack *a = new Allocator32WithCallBack;
219214621f7663896987dc509561c762460226c68c2Kostya Serebryany  a->Init();
220214621f7663896987dc509561c762460226c68c2Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::map_count, 1);  // Allocator state.
221214621f7663896987dc509561c762460226c68c2Kostya Serebryany  a->Allocate(100, 1);
222214621f7663896987dc509561c762460226c68c2Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::map_count, 2);  // alloc.
223214621f7663896987dc509561c762460226c68c2Kostya Serebryany  a->TestOnlyUnmap();
224214621f7663896987dc509561c762460226c68c2Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::unmap_count, 2);  // The whole thing + alloc.
225214621f7663896987dc509561c762460226c68c2Kostya Serebryany  delete a;
226ca661f51dbccc8b8bdeb308751f3b160501f7954Dmitry Vyukov  // fprintf(stderr, "Map: %d Unmap: %d\n",
227ca661f51dbccc8b8bdeb308751f3b160501f7954Dmitry Vyukov  //         TestMapUnmapCallback::map_count,
228ca661f51dbccc8b8bdeb308751f3b160501f7954Dmitry Vyukov  //         TestMapUnmapCallback::unmap_count);
229214621f7663896987dc509561c762460226c68c2Kostya Serebryany}
230214621f7663896987dc509561c762460226c68c2Kostya Serebryany
231214621f7663896987dc509561c762460226c68c2Kostya SerebryanyTEST(SanitizerCommon, LargeMmapAllocatorMapUnmapCallback) {
232214621f7663896987dc509561c762460226c68c2Kostya Serebryany  TestMapUnmapCallback::map_count = 0;
233214621f7663896987dc509561c762460226c68c2Kostya Serebryany  TestMapUnmapCallback::unmap_count = 0;
234214621f7663896987dc509561c762460226c68c2Kostya Serebryany  LargeMmapAllocator<TestMapUnmapCallback> a;
235214621f7663896987dc509561c762460226c68c2Kostya Serebryany  a.Init();
236214621f7663896987dc509561c762460226c68c2Kostya Serebryany  void *x = a.Allocate(1 << 20, 1);
237214621f7663896987dc509561c762460226c68c2Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::map_count, 1);
238214621f7663896987dc509561c762460226c68c2Kostya Serebryany  a.Deallocate(x);
239214621f7663896987dc509561c762460226c68c2Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::unmap_count, 1);
240214621f7663896987dc509561c762460226c68c2Kostya Serebryany}
241214621f7663896987dc509561c762460226c68c2Kostya Serebryany
24272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate<class Allocator>
24372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid FailInAssertionOnOOM() {
24472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  Allocator a;
24572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  a.Init();
24672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const uptr size = 1 << 20;
24772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < 1000000; i++) {
24872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    a.Allocate(size, 1);
24972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
25072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
25172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  a.TestOnlyUnmap();
25272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
25372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
25472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#if SANITIZER_WORDSIZE == 64
25572166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64Overflow) {
25672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  EXPECT_DEATH(FailInAssertionOnOOM<Allocator64>(), "Out of memory");
25772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
25872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
25972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
26072166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, LargeMmapAllocator) {
261214621f7663896987dc509561c762460226c68c2Kostya Serebryany  LargeMmapAllocator<> a;
26272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  a.Init();
26372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
26472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  static const int kNumAllocs = 100;
26572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  void *allocated[kNumAllocs];
26672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  static const uptr size = 1000;
26772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Allocate some.
26872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < kNumAllocs; i++) {
26972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    allocated[i] = a.Allocate(size, 1);
27072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
27172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Deallocate all.
27272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  CHECK_GT(a.TotalMemoryUsed(), size * kNumAllocs);
27372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < kNumAllocs; i++) {
27472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    void *p = allocated[i];
27572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK(a.PointerIsMine(p));
27672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    a.Deallocate(p);
27772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
27872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Check that non left.
27972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  CHECK_EQ(a.TotalMemoryUsed(), 0);
28072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
28172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Allocate some more, also add metadata.
28272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < kNumAllocs; i++) {
28372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    void *x = a.Allocate(size, 1);
28472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_GE(a.GetActuallyAllocatedSize(x), size);
28572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    uptr *meta = reinterpret_cast<uptr*>(a.GetMetaData(x));
28672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    *meta = i;
28772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    allocated[i] = x;
28872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
28972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  CHECK_GT(a.TotalMemoryUsed(), size * kNumAllocs);
29072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Deallocate all in reverse order.
29172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < kNumAllocs; i++) {
29272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    int idx = kNumAllocs - i - 1;
29372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    void *p = allocated[idx];
29472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    uptr *meta = reinterpret_cast<uptr*>(a.GetMetaData(p));
29572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_EQ(*meta, idx);
29672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK(a.PointerIsMine(p));
29772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    a.Deallocate(p);
29872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
29972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  CHECK_EQ(a.TotalMemoryUsed(), 0);
30072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  uptr max_alignment = SANITIZER_WORDSIZE == 64 ? (1 << 28) : (1 << 24);
30172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr alignment = 8; alignment <= max_alignment; alignment *= 2) {
30272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (int i = 0; i < kNumAllocs; i++) {
30372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      uptr size = ((i % 10) + 1) * 4096;
30472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      allocated[i] = a.Allocate(size, alignment);
30572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(0, (uptr)allocated[i] % alignment);
30672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      char *p = (char*)allocated[i];
30772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      p[0] = p[size - 1] = 0;
30872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
30972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (int i = 0; i < kNumAllocs; i++) {
31072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      a.Deallocate(allocated[i]);
31172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
31272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
31372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
31472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
31572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate
31672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany<class PrimaryAllocator, class SecondaryAllocator, class AllocatorCache>
31772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid TestCombinedAllocator() {
318674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  typedef
319674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      CombinedAllocator<PrimaryAllocator, AllocatorCache, SecondaryAllocator>
320674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      Allocator;
321674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  Allocator *a = new Allocator;
322674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  a->Init();
32372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
32472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  AllocatorCache cache;
32572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  cache.Init();
32672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
327674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  EXPECT_EQ(a->Allocate(&cache, -1, 1), (void*)0);
328674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  EXPECT_EQ(a->Allocate(&cache, -1, 1024), (void*)0);
329674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  EXPECT_EQ(a->Allocate(&cache, (uptr)-1 - 1024, 1), (void*)0);
330674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  EXPECT_EQ(a->Allocate(&cache, (uptr)-1 - 1024, 1024), (void*)0);
331674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  EXPECT_EQ(a->Allocate(&cache, (uptr)-1 - 1023, 1024), (void*)0);
33272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
33372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const uptr kNumAllocs = 100000;
33472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const uptr kNumIter = 10;
33572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr iter = 0; iter < kNumIter; iter++) {
33672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    std::vector<void*> allocated;
33772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (uptr i = 0; i < kNumAllocs; i++) {
33872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      uptr size = (i % (1 << 14)) + 1;
33972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      if ((i % 1024) == 0)
34072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        size = 1 << (10 + (i % 14));
341674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      void *x = a->Allocate(&cache, size, 1);
342674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      uptr *meta = reinterpret_cast<uptr*>(a->GetMetaData(x));
34372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(*meta, 0);
34472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      *meta = size;
34572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      allocated.push_back(x);
34672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
34772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
34872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    random_shuffle(allocated.begin(), allocated.end());
34972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
35072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (uptr i = 0; i < kNumAllocs; i++) {
35172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      void *x = allocated[i];
352674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      uptr *meta = reinterpret_cast<uptr*>(a->GetMetaData(x));
35372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_NE(*meta, 0);
354674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      CHECK(a->PointerIsMine(x));
35572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      *meta = 0;
356674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      a->Deallocate(&cache, x);
35772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
35872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    allocated.clear();
359674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany    a->SwallowCache(&cache);
36072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
361674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  a->TestOnlyUnmap();
36272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
36372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
36472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#if SANITIZER_WORDSIZE == 64
365674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya SerebryanyTEST(SanitizerCommon, CombinedAllocator64) {
36672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestCombinedAllocator<Allocator64,
367214621f7663896987dc509561c762460226c68c2Kostya Serebryany      LargeMmapAllocator<>,
36872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      SizeClassAllocatorLocalCache<Allocator64> > ();
36972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
370674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany
371674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya SerebryanyTEST(SanitizerCommon, CombinedAllocator64Compact) {
372674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  TestCombinedAllocator<Allocator64Compact,
373214621f7663896987dc509561c762460226c68c2Kostya Serebryany      LargeMmapAllocator<>,
374674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      SizeClassAllocatorLocalCache<Allocator64Compact> > ();
375674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany}
37672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
37772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
378674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya SerebryanyTEST(SanitizerCommon, CombinedAllocator32Compact) {
379674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  TestCombinedAllocator<Allocator32Compact,
380214621f7663896987dc509561c762460226c68c2Kostya Serebryany      LargeMmapAllocator<>,
381674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      SizeClassAllocatorLocalCache<Allocator32Compact> > ();
382674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany}
383674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany
38472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate <class AllocatorCache>
38572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid TestSizeClassAllocatorLocalCache() {
38672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  static THREADLOCAL AllocatorCache static_allocator_cache;
38772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  static_allocator_cache.Init();
38872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  AllocatorCache cache;
389e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  typedef typename AllocatorCache::Allocator Allocator;
390e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  Allocator *a = new Allocator();
39172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
392e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  a->Init();
39372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  cache.Init();
39472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
39572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const uptr kNumAllocs = 10000;
39672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const int kNumIter = 100;
39772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  uptr saved_total = 0;
39872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < kNumIter; i++) {
39972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    void *allocated[kNumAllocs];
40072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (uptr i = 0; i < kNumAllocs; i++) {
401e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany      allocated[i] = cache.Allocate(a, 0);
40272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
40372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (uptr i = 0; i < kNumAllocs; i++) {
404e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany      cache.Deallocate(a, 0, allocated[i]);
40572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
406e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany    cache.Drain(a);
407e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany    uptr total_allocated = a->TotalMemoryUsed();
40872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    if (saved_total)
40972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(saved_total, total_allocated);
41072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    saved_total = total_allocated;
41172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
41272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
413e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  a->TestOnlyUnmap();
414e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  delete a;
41572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
41672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
41772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#if SANITIZER_WORDSIZE == 64
41872166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64LocalCache) {
41972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassAllocatorLocalCache<
42072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      SizeClassAllocatorLocalCache<Allocator64> >();
42172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
422e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany
423e280ce59d37a67bee14da56a22e205d6562530b0Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64CompactLocalCache) {
424e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  TestSizeClassAllocatorLocalCache<
425e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany      SizeClassAllocatorLocalCache<Allocator64Compact> >();
426e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany}
42772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
428225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov
429e280ce59d37a67bee14da56a22e205d6562530b0Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator32CompactLocalCache) {
430e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  TestSizeClassAllocatorLocalCache<
431e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany      SizeClassAllocatorLocalCache<Allocator32Compact> >();
432e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany}
433e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany
4349fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany#if SANITIZER_WORDSIZE == 64
4359fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryanytypedef SizeClassAllocatorLocalCache<Allocator64> AllocatorCache;
4369fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryanystatic THREADLOCAL AllocatorCache static_allocator_cache;
4379fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany
4389fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryanyvoid *AllocatorLeakTestWorker(void *arg) {
4399fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  typedef AllocatorCache::Allocator Allocator;
4409fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  Allocator *a = (Allocator*)(arg);
4419fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  static_allocator_cache.Allocate(a, 10);
4429fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  static_allocator_cache.Drain(a);
4439fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  return 0;
4449fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany}
4459fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany
4469fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya SerebryanyTEST(SanitizerCommon, AllocatorLeakTest) {
44768acb909db275a9d4fb16b37fab4c42b72671abbAlexey Samsonov  typedef AllocatorCache::Allocator Allocator;
4489fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  Allocator a;
4499fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  a.Init();
4509fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  uptr total_used_memory = 0;
4519fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  for (int i = 0; i < 100; i++) {
4529fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany    pthread_t t;
4539fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany    EXPECT_EQ(0, pthread_create(&t, 0, AllocatorLeakTestWorker, &a));
4549fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany    EXPECT_EQ(0, pthread_join(t, 0));
4559fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany    if (i == 0)
4569fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany      total_used_memory = a.TotalMemoryUsed();
4579fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany    EXPECT_EQ(a.TotalMemoryUsed(), total_used_memory);
4589fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  }
4599fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany
4609fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  a.TestOnlyUnmap();
4619fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany}
4629fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany#endif
4639fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany
464225f53194082f475a5d21780344ff79a2a387c13Dmitry VyukovTEST(Allocator, Basic) {
465225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  char *p = (char*)InternalAlloc(10);
466225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  EXPECT_NE(p, (char*)0);
467225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  char *p2 = (char*)InternalAlloc(20);
468225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  EXPECT_NE(p2, (char*)0);
469225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  EXPECT_NE(p2, p);
470225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  InternalFree(p);
471225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  InternalFree(p2);
472225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov}
473225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov
474225f53194082f475a5d21780344ff79a2a387c13Dmitry VyukovTEST(Allocator, Stress) {
475225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  const int kCount = 1000;
476225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  char *ptrs[kCount];
477225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  unsigned rnd = 42;
478225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  for (int i = 0; i < kCount; i++) {
479225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov    uptr sz = rand_r(&rnd) % 1000;
480225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov    char *p = (char*)InternalAlloc(sz);
481225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov    EXPECT_NE(p, (char*)0);
482225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov    ptrs[i] = p;
483225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  }
484225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  for (int i = 0; i < kCount; i++) {
485225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov    InternalFree(ptrs[i]);
486225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  }
487225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov}
488225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov
4896611abe0c2737a37c1c69f0527a35bb34875221dAlexey SamsonovTEST(Allocator, ScopedBuffer) {
4906611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  const int kSize = 512;
4916611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  {
4926611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov    InternalScopedBuffer<int> int_buf(kSize);
4936611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov    EXPECT_EQ(sizeof(int) * kSize, int_buf.size());  // NOLINT
4946611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  }
4956611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  InternalScopedBuffer<char> char_buf(kSize);
4966611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  EXPECT_EQ(sizeof(char) * kSize, char_buf.size());  // NOLINT
4970bb6e5ddbb11565dfe0a71b0936f0dd76251ea78Kostya Serebryany  internal_memset(char_buf.data(), 'c', kSize);
4986611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  for (int i = 0; i < kSize; i++) {
4996611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov    EXPECT_EQ('c', char_buf[i]);
5006611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  }
5016611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov}
50268902f431172d101f3c6322d96a99d705a37ad95Dmitry Vyukov
50368902f431172d101f3c6322d96a99d705a37ad95Dmitry Vyukov#endif  // #if TSAN_DEBUG==0
504