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"
151f3c2fee395abc36230c445e9ebdba55c4729d35Alexey Samsonov#include "sanitizer_common/sanitizer_allocator_internal.h"
16225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov#include "sanitizer_common/sanitizer_common.h"
1772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
1848ddbef1d051875b2d0b204e8d78300b58d80a85Evgeniy Stepanov#include "sanitizer_test_utils.h"
192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_pthread_wrappers.h"
2048ddbef1d051875b2d0b204e8d78300b58d80a85Evgeniy Stepanov
21225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov#include "gtest/gtest.h"
2272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
23225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov#include <stdlib.h>
2472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#include <algorithm>
2572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#include <vector>
26300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany#include <set>
2772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
2868902f431172d101f3c6322d96a99d705a37ad95Dmitry Vyukov// Too slow for debug build
2986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if !SANITIZER_DEBUG
3068902f431172d101f3c6322d96a99d705a37ad95Dmitry Vyukov
3186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_CAN_USE_ALLOCATOR64
3272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanystatic const uptr kAllocatorSpace = 0x700000000000ULL;
3372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanystatic const uptr kAllocatorSize  = 0x010000000000ULL;  // 1T.
3445595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryanystatic const u64 kAddressSpaceSize = 1ULL << 47;
3572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
3672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytypedef SizeClassAllocator64<
3772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  kAllocatorSpace, kAllocatorSize, 16, DefaultSizeClassMap> Allocator64;
3872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
3972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytypedef SizeClassAllocator64<
4072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  kAllocatorSpace, kAllocatorSize, 16, CompactSizeClassMap> Allocator64Compact;
4186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#elif defined(__mips64)
4286277eb844c4983c81de62d7c050e92fe7155788Stephen Hinesstatic const u64 kAddressSpaceSize = 1ULL << 40;
4345595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany#else
4445595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryanystatic const u64 kAddressSpaceSize = 1ULL << 32;
4572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
4672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
471b54cbfbd12d6302838a6d4d6c42d90bd9c6b9d5Kostya Serebryanystatic const uptr kRegionSizeLog = FIRST_32_SECOND_64(20, 24);
481b54cbfbd12d6302838a6d4d6c42d90bd9c6b9d5Kostya Serebryanystatic const uptr kFlatByteMapSize = kAddressSpaceSize >> kRegionSizeLog;
491b54cbfbd12d6302838a6d4d6c42d90bd9c6b9d5Kostya Serebryany
5045595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryanytypedef SizeClassAllocator32<
511b54cbfbd12d6302838a6d4d6c42d90bd9c6b9d5Kostya Serebryany  0, kAddressSpaceSize,
521b54cbfbd12d6302838a6d4d6c42d90bd9c6b9d5Kostya Serebryany  /*kMetadataSize*/16,
531b54cbfbd12d6302838a6d4d6c42d90bd9c6b9d5Kostya Serebryany  CompactSizeClassMap,
541b54cbfbd12d6302838a6d4d6c42d90bd9c6b9d5Kostya Serebryany  kRegionSizeLog,
551b54cbfbd12d6302838a6d4d6c42d90bd9c6b9d5Kostya Serebryany  FlatByteMap<kFlatByteMapSize> >
561b54cbfbd12d6302838a6d4d6c42d90bd9c6b9d5Kostya Serebryany  Allocator32Compact;
5745595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany
5872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate <class SizeClassMap>
5972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid TestSizeClassMap() {
6072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  typedef SizeClassMap SCMap;
61bb5d0575f9b1100a326f125c7cd8224938af5693Kostya Serebryany  // SCMap::Print();
62038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany  SCMap::Validate();
6372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
6472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
6572166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, DefaultSizeClassMap) {
6672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassMap<DefaultSizeClassMap>();
6772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
6872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
6972166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, CompactSizeClassMap) {
7072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassMap<CompactSizeClassMap>();
7172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
7272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
731f3c2fee395abc36230c445e9ebdba55c4729d35Alexey SamsonovTEST(SanitizerCommon, InternalSizeClassMap) {
741f3c2fee395abc36230c445e9ebdba55c4729d35Alexey Samsonov  TestSizeClassMap<InternalSizeClassMap>();
751f3c2fee395abc36230c445e9ebdba55c4729d35Alexey Samsonov}
761f3c2fee395abc36230c445e9ebdba55c4729d35Alexey Samsonov
7772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate <class Allocator>
7872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid TestSizeClassAllocator() {
7945595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  Allocator *a = new Allocator;
8045595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  a->Init();
81a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov  SizeClassAllocatorLocalCache<Allocator> cache;
82bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  memset(&cache, 0, sizeof(cache));
83bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  cache.Init(0);
8472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
8572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  static const uptr sizes[] = {1, 16, 30, 40, 100, 1000, 10000,
86b1f21c69e02d99944c66e0520d07d8c14d99756fKostya Serebryany    50000, 60000, 100000, 120000, 300000, 500000, 1000000, 2000000};
8772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
8872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  std::vector<void *> allocated;
8972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
9072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  uptr last_total_allocated = 0;
91b1f21c69e02d99944c66e0520d07d8c14d99756fKostya Serebryany  for (int i = 0; i < 3; i++) {
9272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    // Allocate a bunch of chunks.
9345595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany    for (uptr s = 0; s < ARRAY_SIZE(sizes); s++) {
9472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      uptr size = sizes[s];
9545595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany      if (!a->CanAllocate(size, 1)) continue;
9672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      // printf("s = %ld\n", size);
977fe5526c2cb2d88e3ab288aa601a874c47fedb69Evgeniy Stepanov      uptr n_iter = std::max((uptr)6, 8000000 / size);
98b1f21c69e02d99944c66e0520d07d8c14d99756fKostya Serebryany      // fprintf(stderr, "size: %ld iter: %ld\n", size, n_iter);
9972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      for (uptr i = 0; i < n_iter; i++) {
100a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov        uptr class_id0 = Allocator::SizeClassMapT::ClassID(size);
101a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov        char *x = (char*)cache.Allocate(a, class_id0);
102d9b740452db50b47ca16abdc0f5e4bc2abf3afa9Kostya Serebryany        x[0] = 0;
103d9b740452db50b47ca16abdc0f5e4bc2abf3afa9Kostya Serebryany        x[size - 1] = 0;
104d9b740452db50b47ca16abdc0f5e4bc2abf3afa9Kostya Serebryany        x[size / 2] = 0;
10572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        allocated.push_back(x);
1068a41bdc963afdf3c2e14aad64a7cd3291fefd8cfKostya Serebryany        CHECK_EQ(x, a->GetBlockBegin(x));
107d9b740452db50b47ca16abdc0f5e4bc2abf3afa9Kostya Serebryany        CHECK_EQ(x, a->GetBlockBegin(x + size - 1));
10845595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany        CHECK(a->PointerIsMine(x));
109da1f82bcbe50b28d11e93eacdcd529e9f0e2ef38Kostya Serebryany        CHECK(a->PointerIsMine(x + size - 1));
110da1f82bcbe50b28d11e93eacdcd529e9f0e2ef38Kostya Serebryany        CHECK(a->PointerIsMine(x + size / 2));
11145595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany        CHECK_GE(a->GetActuallyAllocatedSize(x), size);
11245595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany        uptr class_id = a->GetSizeClass(x);
11372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        CHECK_EQ(class_id, Allocator::SizeClassMapT::ClassID(size));
11445595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany        uptr *metadata = reinterpret_cast<uptr*>(a->GetMetaData(x));
11572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        metadata[0] = reinterpret_cast<uptr>(x) + 1;
11672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        metadata[1] = 0xABCD;
11772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      }
11872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
11972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    // Deallocate all.
12072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (uptr i = 0; i < allocated.size(); i++) {
12172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      void *x = allocated[i];
12245595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany      uptr *metadata = reinterpret_cast<uptr*>(a->GetMetaData(x));
12372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(metadata[0], reinterpret_cast<uptr>(x) + 1);
12472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(metadata[1], 0xABCD);
125a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov      cache.Deallocate(a, a->GetSizeClass(x), x);
12672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
12772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    allocated.clear();
12845595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany    uptr total_allocated = a->TotalMemoryUsed();
12972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    if (last_total_allocated == 0)
13072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      last_total_allocated = total_allocated;
13172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_EQ(last_total_allocated, total_allocated);
13272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
13372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
134aa0f20dca32ad6ed0d4f5623b393dd700375f12aKostya Serebryany  // Check that GetBlockBegin never crashes.
135aa0f20dca32ad6ed0d4f5623b393dd700375f12aKostya Serebryany  for (uptr x = 0, step = kAddressSpaceSize / 100000;
136aa0f20dca32ad6ed0d4f5623b393dd700375f12aKostya Serebryany       x < kAddressSpaceSize - step; x += step)
137aa0f20dca32ad6ed0d4f5623b393dd700375f12aKostya Serebryany    if (a->PointerIsMine(reinterpret_cast<void *>(x)))
138aa0f20dca32ad6ed0d4f5623b393dd700375f12aKostya Serebryany      Ident(a->GetBlockBegin(reinterpret_cast<void *>(x)));
139aa0f20dca32ad6ed0d4f5623b393dd700375f12aKostya Serebryany
14045595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  a->TestOnlyUnmap();
14145595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  delete a;
14272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
14372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
14486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_CAN_USE_ALLOCATOR64
14572166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64) {
14672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassAllocator<Allocator64>();
14772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
14872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
14972166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64Compact) {
15072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassAllocator<Allocator64Compact>();
15172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
15272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
15372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
15445595ba6b77b54b8212389cba6b95dc634122145Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator32Compact) {
15545595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  TestSizeClassAllocator<Allocator32Compact>();
15645595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany}
15745595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany
15872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate <class Allocator>
159784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryanyvoid SizeClassAllocatorMetadataStress() {
160784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  Allocator *a = new Allocator;
161784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  a->Init();
162a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov  SizeClassAllocatorLocalCache<Allocator> cache;
163bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  memset(&cache, 0, sizeof(cache));
164bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  cache.Init(0);
16572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
166871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany  const uptr kNumAllocs = 1 << 13;
16772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  void *allocated[kNumAllocs];
168871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany  void *meta[kNumAllocs];
16972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr i = 0; i < kNumAllocs; i++) {
170a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov    void *x = cache.Allocate(a, 1 + i % 50);
17172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    allocated[i] = x;
172871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany    meta[i] = a->GetMetaData(x);
17372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
17472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Get Metadata kNumAllocs^2 times.
17572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr i = 0; i < kNumAllocs * kNumAllocs; i++) {
176871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany    uptr idx = i % kNumAllocs;
177871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany    void *m = a->GetMetaData(allocated[idx]);
178871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany    EXPECT_EQ(m, meta[idx]);
17972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
18072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr i = 0; i < kNumAllocs; i++) {
181a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov    cache.Deallocate(a, 1 + i % 50, allocated[i]);
18272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
18372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
184784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  a->TestOnlyUnmap();
185784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  delete a;
18672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
18772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
18886277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_CAN_USE_ALLOCATOR64
18972166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64MetadataStress) {
190784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  SizeClassAllocatorMetadataStress<Allocator64>();
19172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
192225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov
19372166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64CompactMetadataStress) {
194784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  SizeClassAllocatorMetadataStress<Allocator64Compact>();
19572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
19686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif  // SANITIZER_CAN_USE_ALLOCATOR64
197784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator32CompactMetadataStress) {
198784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  SizeClassAllocatorMetadataStress<Allocator32Compact>();
199784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany}
20072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
201a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryanytemplate <class Allocator>
202a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryanyvoid SizeClassAllocatorGetBlockBeginStress() {
203a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  Allocator *a = new Allocator;
204a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  a->Init();
205a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  SizeClassAllocatorLocalCache<Allocator> cache;
206a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  memset(&cache, 0, sizeof(cache));
207a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  cache.Init(0);
208a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany
209a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  uptr max_size_class = Allocator::kNumClasses - 1;
210a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  uptr size = Allocator::SizeClassMapT::Size(max_size_class);
211a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  u64 G8 = 1ULL << 33;
212871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany  // Make sure we correctly compute GetBlockBegin() w/o overflow.
213a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  for (size_t i = 0; i <= G8 / size; i++) {
214a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany    void *x = cache.Allocate(a, max_size_class);
215a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany    void *beg = a->GetBlockBegin(x);
216374fd35926d1c4877ac26ca8e2877154cb698cb5Dmitry Vyukov    // if ((i & (i - 1)) == 0)
217374fd35926d1c4877ac26ca8e2877154cb698cb5Dmitry Vyukov    //   fprintf(stderr, "[%zd] %p %p\n", i, x, beg);
218a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany    EXPECT_EQ(x, beg);
219a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  }
220a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany
221a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  a->TestOnlyUnmap();
222a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  delete a;
223a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany}
224a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany
22586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_CAN_USE_ALLOCATOR64
226871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64GetBlockBegin) {
227a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  SizeClassAllocatorGetBlockBeginStress<Allocator64>();
228a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany}
229871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64CompactGetBlockBegin) {
230871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany  SizeClassAllocatorGetBlockBeginStress<Allocator64Compact>();
231871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany}
232871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator32CompactGetBlockBegin) {
233871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany  SizeClassAllocatorGetBlockBeginStress<Allocator32Compact>();
234871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany}
23586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif  // SANITIZER_CAN_USE_ALLOCATOR64
236a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany
237214621f7663896987dc509561c762460226c68c2Kostya Serebryanystruct TestMapUnmapCallback {
238214621f7663896987dc509561c762460226c68c2Kostya Serebryany  static int map_count, unmap_count;
239214621f7663896987dc509561c762460226c68c2Kostya Serebryany  void OnMap(uptr p, uptr size) const { map_count++; }
240214621f7663896987dc509561c762460226c68c2Kostya Serebryany  void OnUnmap(uptr p, uptr size) const { unmap_count++; }
241214621f7663896987dc509561c762460226c68c2Kostya Serebryany};
242214621f7663896987dc509561c762460226c68c2Kostya Serebryanyint TestMapUnmapCallback::map_count;
243214621f7663896987dc509561c762460226c68c2Kostya Serebryanyint TestMapUnmapCallback::unmap_count;
244214621f7663896987dc509561c762460226c68c2Kostya Serebryany
24586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_CAN_USE_ALLOCATOR64
246214621f7663896987dc509561c762460226c68c2Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64MapUnmapCallback) {
247214621f7663896987dc509561c762460226c68c2Kostya Serebryany  TestMapUnmapCallback::map_count = 0;
248214621f7663896987dc509561c762460226c68c2Kostya Serebryany  TestMapUnmapCallback::unmap_count = 0;
249214621f7663896987dc509561c762460226c68c2Kostya Serebryany  typedef SizeClassAllocator64<
250214621f7663896987dc509561c762460226c68c2Kostya Serebryany      kAllocatorSpace, kAllocatorSize, 16, DefaultSizeClassMap,
251214621f7663896987dc509561c762460226c68c2Kostya Serebryany      TestMapUnmapCallback> Allocator64WithCallBack;
252214621f7663896987dc509561c762460226c68c2Kostya Serebryany  Allocator64WithCallBack *a = new Allocator64WithCallBack;
253214621f7663896987dc509561c762460226c68c2Kostya Serebryany  a->Init();
254214621f7663896987dc509561c762460226c68c2Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::map_count, 1);  // Allocator state.
255a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov  SizeClassAllocatorLocalCache<Allocator64WithCallBack> cache;
256bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  memset(&cache, 0, sizeof(cache));
257bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  cache.Init(0);
258bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  AllocatorStats stats;
259bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  stats.Init();
260f2c417c3b7d7a11f1f6f20edca08af2cb1fad142Kostya Serebryany  a->AllocateBatch(&stats, &cache, 32);
261567ad078d73babb2c8addfbebb1ddd6cd0085c53Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::map_count, 3);  // State + alloc + metadata.
262214621f7663896987dc509561c762460226c68c2Kostya Serebryany  a->TestOnlyUnmap();
263214621f7663896987dc509561c762460226c68c2Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::unmap_count, 1);  // The whole thing.
264214621f7663896987dc509561c762460226c68c2Kostya Serebryany  delete a;
265214621f7663896987dc509561c762460226c68c2Kostya Serebryany}
266214621f7663896987dc509561c762460226c68c2Kostya Serebryany#endif
267214621f7663896987dc509561c762460226c68c2Kostya Serebryany
268214621f7663896987dc509561c762460226c68c2Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator32MapUnmapCallback) {
269214621f7663896987dc509561c762460226c68c2Kostya Serebryany  TestMapUnmapCallback::map_count = 0;
270214621f7663896987dc509561c762460226c68c2Kostya Serebryany  TestMapUnmapCallback::unmap_count = 0;
271214621f7663896987dc509561c762460226c68c2Kostya Serebryany  typedef SizeClassAllocator32<
2721b54cbfbd12d6302838a6d4d6c42d90bd9c6b9d5Kostya Serebryany      0, kAddressSpaceSize,
2731b54cbfbd12d6302838a6d4d6c42d90bd9c6b9d5Kostya Serebryany      /*kMetadataSize*/16,
2741b54cbfbd12d6302838a6d4d6c42d90bd9c6b9d5Kostya Serebryany      CompactSizeClassMap,
2751b54cbfbd12d6302838a6d4d6c42d90bd9c6b9d5Kostya Serebryany      kRegionSizeLog,
2761b54cbfbd12d6302838a6d4d6c42d90bd9c6b9d5Kostya Serebryany      FlatByteMap<kFlatByteMapSize>,
2771b54cbfbd12d6302838a6d4d6c42d90bd9c6b9d5Kostya Serebryany      TestMapUnmapCallback>
2781b54cbfbd12d6302838a6d4d6c42d90bd9c6b9d5Kostya Serebryany    Allocator32WithCallBack;
279214621f7663896987dc509561c762460226c68c2Kostya Serebryany  Allocator32WithCallBack *a = new Allocator32WithCallBack;
280214621f7663896987dc509561c762460226c68c2Kostya Serebryany  a->Init();
2811b54cbfbd12d6302838a6d4d6c42d90bd9c6b9d5Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::map_count, 0);
282a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov  SizeClassAllocatorLocalCache<Allocator32WithCallBack>  cache;
283bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  memset(&cache, 0, sizeof(cache));
284bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  cache.Init(0);
285bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  AllocatorStats stats;
286bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  stats.Init();
287f2c417c3b7d7a11f1f6f20edca08af2cb1fad142Kostya Serebryany  a->AllocateBatch(&stats, &cache, 32);
2881b54cbfbd12d6302838a6d4d6c42d90bd9c6b9d5Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::map_count, 1);
289214621f7663896987dc509561c762460226c68c2Kostya Serebryany  a->TestOnlyUnmap();
2901b54cbfbd12d6302838a6d4d6c42d90bd9c6b9d5Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::unmap_count, 1);
291214621f7663896987dc509561c762460226c68c2Kostya Serebryany  delete a;
292ca661f51dbccc8b8bdeb308751f3b160501f7954Dmitry Vyukov  // fprintf(stderr, "Map: %d Unmap: %d\n",
293ca661f51dbccc8b8bdeb308751f3b160501f7954Dmitry Vyukov  //         TestMapUnmapCallback::map_count,
294ca661f51dbccc8b8bdeb308751f3b160501f7954Dmitry Vyukov  //         TestMapUnmapCallback::unmap_count);
295214621f7663896987dc509561c762460226c68c2Kostya Serebryany}
296214621f7663896987dc509561c762460226c68c2Kostya Serebryany
297214621f7663896987dc509561c762460226c68c2Kostya SerebryanyTEST(SanitizerCommon, LargeMmapAllocatorMapUnmapCallback) {
298214621f7663896987dc509561c762460226c68c2Kostya Serebryany  TestMapUnmapCallback::map_count = 0;
299214621f7663896987dc509561c762460226c68c2Kostya Serebryany  TestMapUnmapCallback::unmap_count = 0;
300214621f7663896987dc509561c762460226c68c2Kostya Serebryany  LargeMmapAllocator<TestMapUnmapCallback> a;
30186277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  a.Init(/* may_return_null */ false);
302bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  AllocatorStats stats;
303bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  stats.Init();
304bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  void *x = a.Allocate(&stats, 1 << 20, 1);
305214621f7663896987dc509561c762460226c68c2Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::map_count, 1);
306bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  a.Deallocate(&stats, x);
307214621f7663896987dc509561c762460226c68c2Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::unmap_count, 1);
308214621f7663896987dc509561c762460226c68c2Kostya Serebryany}
309214621f7663896987dc509561c762460226c68c2Kostya Serebryany
31072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate<class Allocator>
31172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid FailInAssertionOnOOM() {
31272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  Allocator a;
31372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  a.Init();
314a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov  SizeClassAllocatorLocalCache<Allocator> cache;
315bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  memset(&cache, 0, sizeof(cache));
316bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  cache.Init(0);
317bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  AllocatorStats stats;
318bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  stats.Init();
31972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < 1000000; i++) {
320f2c417c3b7d7a11f1f6f20edca08af2cb1fad142Kostya Serebryany    a.AllocateBatch(&stats, &cache, 52);
32172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
32272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
32372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  a.TestOnlyUnmap();
32472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
32572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
32686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_CAN_USE_ALLOCATOR64
32772166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64Overflow) {
32872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  EXPECT_DEATH(FailInAssertionOnOOM<Allocator64>(), "Out of memory");
32972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
33072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
33172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
3322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !defined(_WIN32)  // FIXME: This currently fails on Windows.
33372166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, LargeMmapAllocator) {
334214621f7663896987dc509561c762460226c68c2Kostya Serebryany  LargeMmapAllocator<> a;
33586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  a.Init(/* may_return_null */ false);
336bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  AllocatorStats stats;
337bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  stats.Init();
33872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
339b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany  static const int kNumAllocs = 1000;
340da1f82bcbe50b28d11e93eacdcd529e9f0e2ef38Kostya Serebryany  char *allocated[kNumAllocs];
341b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany  static const uptr size = 4000;
34272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Allocate some.
34372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < kNumAllocs; i++) {
344bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov    allocated[i] = (char *)a.Allocate(&stats, size, 1);
345b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany    CHECK(a.PointerIsMine(allocated[i]));
34672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
34772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Deallocate all.
34872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  CHECK_GT(a.TotalMemoryUsed(), size * kNumAllocs);
34972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < kNumAllocs; i++) {
350da1f82bcbe50b28d11e93eacdcd529e9f0e2ef38Kostya Serebryany    char *p = allocated[i];
35172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK(a.PointerIsMine(p));
352bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov    a.Deallocate(&stats, p);
35372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
35472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Check that non left.
35572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  CHECK_EQ(a.TotalMemoryUsed(), 0);
35672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
35772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Allocate some more, also add metadata.
35872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < kNumAllocs; i++) {
359bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov    char *x = (char *)a.Allocate(&stats, size, 1);
36072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_GE(a.GetActuallyAllocatedSize(x), size);
36172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    uptr *meta = reinterpret_cast<uptr*>(a.GetMetaData(x));
36272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    *meta = i;
36372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    allocated[i] = x;
36472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
365b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany  for (int i = 0; i < kNumAllocs * kNumAllocs; i++) {
366b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany    char *p = allocated[i % kNumAllocs];
367b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany    CHECK(a.PointerIsMine(p));
368b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany    CHECK(a.PointerIsMine(p + 2000));
369b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany  }
37072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  CHECK_GT(a.TotalMemoryUsed(), size * kNumAllocs);
37172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Deallocate all in reverse order.
37272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < kNumAllocs; i++) {
37372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    int idx = kNumAllocs - i - 1;
374da1f82bcbe50b28d11e93eacdcd529e9f0e2ef38Kostya Serebryany    char *p = allocated[idx];
37572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    uptr *meta = reinterpret_cast<uptr*>(a.GetMetaData(p));
37672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_EQ(*meta, idx);
37772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK(a.PointerIsMine(p));
378bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov    a.Deallocate(&stats, p);
37972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
38072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  CHECK_EQ(a.TotalMemoryUsed(), 0);
381b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany
382b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany  // Test alignments.
38372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  uptr max_alignment = SANITIZER_WORDSIZE == 64 ? (1 << 28) : (1 << 24);
38472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr alignment = 8; alignment <= max_alignment; alignment *= 2) {
385b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany    const uptr kNumAlignedAllocs = 100;
38668d3a1bae35be595faf7d9f028a268f390501029Kostya Serebryany    for (uptr i = 0; i < kNumAlignedAllocs; i++) {
38772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      uptr size = ((i % 10) + 1) * 4096;
388bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov      char *p = allocated[i] = (char *)a.Allocate(&stats, size, alignment);
389da1f82bcbe50b28d11e93eacdcd529e9f0e2ef38Kostya Serebryany      CHECK_EQ(p, a.GetBlockBegin(p));
390da1f82bcbe50b28d11e93eacdcd529e9f0e2ef38Kostya Serebryany      CHECK_EQ(p, a.GetBlockBegin(p + size - 1));
391da1f82bcbe50b28d11e93eacdcd529e9f0e2ef38Kostya Serebryany      CHECK_EQ(p, a.GetBlockBegin(p + size / 2));
39272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(0, (uptr)allocated[i] % alignment);
39372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      p[0] = p[size - 1] = 0;
39472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
39568d3a1bae35be595faf7d9f028a268f390501029Kostya Serebryany    for (uptr i = 0; i < kNumAlignedAllocs; i++) {
396bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov      a.Deallocate(&stats, allocated[i]);
39772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
39872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
399a2c1d98745a9e8e860948004423d0072424f48b7Kostya Serebryany
400a2c1d98745a9e8e860948004423d0072424f48b7Kostya Serebryany  // Regression test for boundary condition in GetBlockBegin().
401a2c1d98745a9e8e860948004423d0072424f48b7Kostya Serebryany  uptr page_size = GetPageSizeCached();
402a2c1d98745a9e8e860948004423d0072424f48b7Kostya Serebryany  char *p = (char *)a.Allocate(&stats, page_size, 1);
403a2c1d98745a9e8e860948004423d0072424f48b7Kostya Serebryany  CHECK_EQ(p, a.GetBlockBegin(p));
404a2c1d98745a9e8e860948004423d0072424f48b7Kostya Serebryany  CHECK_EQ(p, (char *)a.GetBlockBegin(p + page_size - 1));
405a2c1d98745a9e8e860948004423d0072424f48b7Kostya Serebryany  CHECK_NE(p, (char *)a.GetBlockBegin(p + page_size));
406a2c1d98745a9e8e860948004423d0072424f48b7Kostya Serebryany  a.Deallocate(&stats, p);
40772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
4082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
40972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
41072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate
41172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany<class PrimaryAllocator, class SecondaryAllocator, class AllocatorCache>
41272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid TestCombinedAllocator() {
413674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  typedef
414674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      CombinedAllocator<PrimaryAllocator, AllocatorCache, SecondaryAllocator>
415674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      Allocator;
416674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  Allocator *a = new Allocator;
41786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  a->Init(/* may_return_null */ true);
41872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
41972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  AllocatorCache cache;
420bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  memset(&cache, 0, sizeof(cache));
421bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  a->InitCache(&cache);
42272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
423674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  EXPECT_EQ(a->Allocate(&cache, -1, 1), (void*)0);
424674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  EXPECT_EQ(a->Allocate(&cache, -1, 1024), (void*)0);
425674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  EXPECT_EQ(a->Allocate(&cache, (uptr)-1 - 1024, 1), (void*)0);
426674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  EXPECT_EQ(a->Allocate(&cache, (uptr)-1 - 1024, 1024), (void*)0);
427674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  EXPECT_EQ(a->Allocate(&cache, (uptr)-1 - 1023, 1024), (void*)0);
42872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
42986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  // Set to false
43086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  a->SetMayReturnNull(false);
4319150f397ba4c5478275d72665ea3e53a84c7076aKostya Serebryany  EXPECT_DEATH(a->Allocate(&cache, -1, 1),
4329150f397ba4c5478275d72665ea3e53a84c7076aKostya Serebryany               "allocator is terminating the process");
4339150f397ba4c5478275d72665ea3e53a84c7076aKostya Serebryany
43472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const uptr kNumAllocs = 100000;
43572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const uptr kNumIter = 10;
43672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr iter = 0; iter < kNumIter; iter++) {
43772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    std::vector<void*> allocated;
43872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (uptr i = 0; i < kNumAllocs; i++) {
43972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      uptr size = (i % (1 << 14)) + 1;
44072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      if ((i % 1024) == 0)
44172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        size = 1 << (10 + (i % 14));
442674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      void *x = a->Allocate(&cache, size, 1);
443674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      uptr *meta = reinterpret_cast<uptr*>(a->GetMetaData(x));
44472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(*meta, 0);
44572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      *meta = size;
44672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      allocated.push_back(x);
44772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
44872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
44972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    random_shuffle(allocated.begin(), allocated.end());
45072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
45172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (uptr i = 0; i < kNumAllocs; i++) {
45272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      void *x = allocated[i];
453674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      uptr *meta = reinterpret_cast<uptr*>(a->GetMetaData(x));
45472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_NE(*meta, 0);
455674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      CHECK(a->PointerIsMine(x));
45672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      *meta = 0;
457674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      a->Deallocate(&cache, x);
45872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
45972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    allocated.clear();
460674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany    a->SwallowCache(&cache);
46172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
462bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  a->DestroyCache(&cache);
463674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  a->TestOnlyUnmap();
46472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
46572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
46686277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_CAN_USE_ALLOCATOR64
467674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya SerebryanyTEST(SanitizerCommon, CombinedAllocator64) {
46872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestCombinedAllocator<Allocator64,
469214621f7663896987dc509561c762460226c68c2Kostya Serebryany      LargeMmapAllocator<>,
47072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      SizeClassAllocatorLocalCache<Allocator64> > ();
47172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
472674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany
473674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya SerebryanyTEST(SanitizerCommon, CombinedAllocator64Compact) {
474674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  TestCombinedAllocator<Allocator64Compact,
475214621f7663896987dc509561c762460226c68c2Kostya Serebryany      LargeMmapAllocator<>,
476674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      SizeClassAllocatorLocalCache<Allocator64Compact> > ();
477674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany}
47872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
47972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
4802d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#if !defined(_WIN32)  // FIXME: This currently fails on Windows.
481674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya SerebryanyTEST(SanitizerCommon, CombinedAllocator32Compact) {
482674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  TestCombinedAllocator<Allocator32Compact,
483214621f7663896987dc509561c762460226c68c2Kostya Serebryany      LargeMmapAllocator<>,
484674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      SizeClassAllocatorLocalCache<Allocator32Compact> > ();
485674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany}
4862d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
487674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany
48872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate <class AllocatorCache>
48972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid TestSizeClassAllocatorLocalCache() {
49072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  AllocatorCache cache;
491e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  typedef typename AllocatorCache::Allocator Allocator;
492e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  Allocator *a = new Allocator();
49372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
494e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  a->Init();
495bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  memset(&cache, 0, sizeof(cache));
496bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  cache.Init(0);
49772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
49872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const uptr kNumAllocs = 10000;
49972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const int kNumIter = 100;
50072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  uptr saved_total = 0;
501038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany  for (int class_id = 1; class_id <= 5; class_id++) {
502b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany    for (int it = 0; it < kNumIter; it++) {
503038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany      void *allocated[kNumAllocs];
504038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany      for (uptr i = 0; i < kNumAllocs; i++) {
505038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany        allocated[i] = cache.Allocate(a, class_id);
506038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany      }
507038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany      for (uptr i = 0; i < kNumAllocs; i++) {
508038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany        cache.Deallocate(a, class_id, allocated[i]);
509038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany      }
510038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany      cache.Drain(a);
511038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany      uptr total_allocated = a->TotalMemoryUsed();
512b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany      if (it)
513038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany        CHECK_EQ(saved_total, total_allocated);
514038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany      saved_total = total_allocated;
51572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
51672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
51772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
518e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  a->TestOnlyUnmap();
519e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  delete a;
52072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
52172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
52286277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_CAN_USE_ALLOCATOR64
52372166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64LocalCache) {
52472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassAllocatorLocalCache<
52572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      SizeClassAllocatorLocalCache<Allocator64> >();
52672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
527e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany
528e280ce59d37a67bee14da56a22e205d6562530b0Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64CompactLocalCache) {
529e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  TestSizeClassAllocatorLocalCache<
530e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany      SizeClassAllocatorLocalCache<Allocator64Compact> >();
531e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany}
53272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
533225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov
534e280ce59d37a67bee14da56a22e205d6562530b0Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator32CompactLocalCache) {
535e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  TestSizeClassAllocatorLocalCache<
536e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany      SizeClassAllocatorLocalCache<Allocator32Compact> >();
537e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany}
538e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany
53986277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_CAN_USE_ALLOCATOR64
5409fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryanytypedef SizeClassAllocatorLocalCache<Allocator64> AllocatorCache;
5410d02d75ca1e34217cb762ec2b5cc13a88993ba94Evgeniy Stepanovstatic AllocatorCache static_allocator_cache;
5429fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany
5439fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryanyvoid *AllocatorLeakTestWorker(void *arg) {
5449fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  typedef AllocatorCache::Allocator Allocator;
5459fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  Allocator *a = (Allocator*)(arg);
5469fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  static_allocator_cache.Allocate(a, 10);
5479fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  static_allocator_cache.Drain(a);
5489fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  return 0;
5499fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany}
5509fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany
5519fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya SerebryanyTEST(SanitizerCommon, AllocatorLeakTest) {
55268acb909db275a9d4fb16b37fab4c42b72671abbAlexey Samsonov  typedef AllocatorCache::Allocator Allocator;
5539fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  Allocator a;
5549fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  a.Init();
5559fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  uptr total_used_memory = 0;
5569fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  for (int i = 0; i < 100; i++) {
5579fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany    pthread_t t;
5582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    PTHREAD_CREATE(&t, 0, AllocatorLeakTestWorker, &a);
5592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    PTHREAD_JOIN(t, 0);
5609fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany    if (i == 0)
5619fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany      total_used_memory = a.TotalMemoryUsed();
5629fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany    EXPECT_EQ(a.TotalMemoryUsed(), total_used_memory);
5639fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  }
5649fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany
5659fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  a.TestOnlyUnmap();
5669fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany}
5675d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner
5685d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner// Struct which is allocated to pass info to new threads.  The new thread frees
5695d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner// it.
5705d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Klecknerstruct NewThreadParams {
5715d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  AllocatorCache *thread_cache;
5725d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  AllocatorCache::Allocator *allocator;
5735d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  uptr class_id;
5745d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner};
5755d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner
5765d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner// Called in a new thread.  Just frees its argument.
5775d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Klecknerstatic void *DeallocNewThreadWorker(void *arg) {
5785d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  NewThreadParams *params = reinterpret_cast<NewThreadParams*>(arg);
5795d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  params->thread_cache->Deallocate(params->allocator, params->class_id, params);
5805d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  return NULL;
5815d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner}
5825d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner
5835d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner// The allocator cache is supposed to be POD and zero initialized.  We should be
5845d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner// able to call Deallocate on a zeroed cache, and it will self-initialize.
5855d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid KlecknerTEST(Allocator, AllocatorCacheDeallocNewThread) {
5865d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  AllocatorCache::Allocator allocator;
5875d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  allocator.Init();
5885d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  AllocatorCache main_cache;
5895d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  AllocatorCache child_cache;
5905d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  memset(&main_cache, 0, sizeof(main_cache));
5915d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  memset(&child_cache, 0, sizeof(child_cache));
5925d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner
5935d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  uptr class_id = DefaultSizeClassMap::ClassID(sizeof(NewThreadParams));
5945d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  NewThreadParams *params = reinterpret_cast<NewThreadParams*>(
5955d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner      main_cache.Allocate(&allocator, class_id));
5965d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  params->thread_cache = &child_cache;
5975d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  params->allocator = &allocator;
5985d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  params->class_id = class_id;
5995d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  pthread_t t;
6002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  PTHREAD_CREATE(&t, 0, DeallocNewThreadWorker, params);
6012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  PTHREAD_JOIN(t, 0);
6025d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner}
6039fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany#endif
6049fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany
605225f53194082f475a5d21780344ff79a2a387c13Dmitry VyukovTEST(Allocator, Basic) {
606225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  char *p = (char*)InternalAlloc(10);
607225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  EXPECT_NE(p, (char*)0);
608225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  char *p2 = (char*)InternalAlloc(20);
609225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  EXPECT_NE(p2, (char*)0);
610225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  EXPECT_NE(p2, p);
611225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  InternalFree(p);
612225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  InternalFree(p2);
613225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov}
614225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov
615225f53194082f475a5d21780344ff79a2a387c13Dmitry VyukovTEST(Allocator, Stress) {
616225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  const int kCount = 1000;
617225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  char *ptrs[kCount];
618225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  unsigned rnd = 42;
619225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  for (int i = 0; i < kCount; i++) {
62048ddbef1d051875b2d0b204e8d78300b58d80a85Evgeniy Stepanov    uptr sz = my_rand_r(&rnd) % 1000;
621225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov    char *p = (char*)InternalAlloc(sz);
622225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov    EXPECT_NE(p, (char*)0);
623225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov    ptrs[i] = p;
624225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  }
625225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  for (int i = 0; i < kCount; i++) {
626225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov    InternalFree(ptrs[i]);
627225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  }
628225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov}
629225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov
6306d1862363c88c183b0ed7740fca876342cf0474bStephen HinesTEST(Allocator, LargeAlloc) {
6316d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  void *p = InternalAlloc(10 << 20);
6326d1862363c88c183b0ed7740fca876342cf0474bStephen Hines  InternalFree(p);
6331f3c2fee395abc36230c445e9ebdba55c4729d35Alexey Samsonov}
6341f3c2fee395abc36230c445e9ebdba55c4729d35Alexey Samsonov
6356611abe0c2737a37c1c69f0527a35bb34875221dAlexey SamsonovTEST(Allocator, ScopedBuffer) {
6366611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  const int kSize = 512;
6376611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  {
6386611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov    InternalScopedBuffer<int> int_buf(kSize);
6396611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov    EXPECT_EQ(sizeof(int) * kSize, int_buf.size());  // NOLINT
6406611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  }
6416611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  InternalScopedBuffer<char> char_buf(kSize);
6426611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  EXPECT_EQ(sizeof(char) * kSize, char_buf.size());  // NOLINT
6430bb6e5ddbb11565dfe0a71b0936f0dd76251ea78Kostya Serebryany  internal_memset(char_buf.data(), 'c', kSize);
6446611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  for (int i = 0; i < kSize; i++) {
6456611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov    EXPECT_EQ('c', char_buf[i]);
6466611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  }
6476611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov}
64868902f431172d101f3c6322d96a99d705a37ad95Dmitry Vyukov
649ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveevvoid IterationTestCallback(uptr chunk, void *arg) {
650ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev  reinterpret_cast<std::set<uptr> *>(arg)->insert(chunk);
651c87f737d972a96a05c85ef9be03d0f40890c653fSergey Matveev}
652300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
653300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryanytemplate <class Allocator>
654300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryanyvoid TestSizeClassAllocatorIteration() {
655300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  Allocator *a = new Allocator;
656300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  a->Init();
657300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  SizeClassAllocatorLocalCache<Allocator> cache;
658300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  memset(&cache, 0, sizeof(cache));
659300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  cache.Init(0);
660300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
661300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  static const uptr sizes[] = {1, 16, 30, 40, 100, 1000, 10000,
662300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    50000, 60000, 100000, 120000, 300000, 500000, 1000000, 2000000};
663300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
664300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  std::vector<void *> allocated;
665300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
666300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  // Allocate a bunch of chunks.
667300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  for (uptr s = 0; s < ARRAY_SIZE(sizes); s++) {
668300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    uptr size = sizes[s];
669300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    if (!a->CanAllocate(size, 1)) continue;
670300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    // printf("s = %ld\n", size);
671300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    uptr n_iter = std::max((uptr)6, 80000 / size);
672300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    // fprintf(stderr, "size: %ld iter: %ld\n", size, n_iter);
673300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    for (uptr j = 0; j < n_iter; j++) {
674300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany      uptr class_id0 = Allocator::SizeClassMapT::ClassID(size);
675300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany      void *x = cache.Allocate(a, class_id0);
676300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany      allocated.push_back(x);
677300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    }
678300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  }
679300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
680ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev  std::set<uptr> reported_chunks;
681300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  a->ForceLock();
682ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev  a->ForEachChunk(IterationTestCallback, &reported_chunks);
683300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  a->ForceUnlock();
684300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
685300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  for (uptr i = 0; i < allocated.size(); i++) {
686300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    // Don't use EXPECT_NE. Reporting the first mismatch is enough.
687ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev    ASSERT_NE(reported_chunks.find(reinterpret_cast<uptr>(allocated[i])),
688ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev              reported_chunks.end());
689300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  }
690300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
691300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  a->TestOnlyUnmap();
692300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  delete a;
693300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany}
694300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
69586277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_CAN_USE_ALLOCATOR64
696300f9534eeed62339eb8b73722d4142c60238ffcKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64Iteration) {
697300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  TestSizeClassAllocatorIteration<Allocator64>();
698300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany}
699300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany#endif
700300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
701300f9534eeed62339eb8b73722d4142c60238ffcKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator32Iteration) {
702300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  TestSizeClassAllocatorIteration<Allocator32Compact>();
703300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany}
704300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
705300f9534eeed62339eb8b73722d4142c60238ffcKostya SerebryanyTEST(SanitizerCommon, LargeMmapAllocatorIteration) {
706300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  LargeMmapAllocator<> a;
70786277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  a.Init(/* may_return_null */ false);
708300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  AllocatorStats stats;
709300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  stats.Init();
710300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
7116c876e428923295706f63fee68ef35d2f0fbaec5Kostya Serebryany  static const uptr kNumAllocs = 1000;
712300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  char *allocated[kNumAllocs];
713300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  static const uptr size = 40;
714300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  // Allocate some.
715f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany  for (uptr i = 0; i < kNumAllocs; i++)
716300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    allocated[i] = (char *)a.Allocate(&stats, size, 1);
717300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
718ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev  std::set<uptr> reported_chunks;
719300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  a.ForceLock();
720ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev  a.ForEachChunk(IterationTestCallback, &reported_chunks);
721300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  a.ForceUnlock();
722300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
723300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  for (uptr i = 0; i < kNumAllocs; i++) {
724300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    // Don't use EXPECT_NE. Reporting the first mismatch is enough.
725ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev    ASSERT_NE(reported_chunks.find(reinterpret_cast<uptr>(allocated[i])),
726ac78d0087281e9b40bb043f827fbde8c05c6505aSergey Matveev              reported_chunks.end());
727300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  }
728f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany  for (uptr i = 0; i < kNumAllocs; i++)
729f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany    a.Deallocate(&stats, allocated[i]);
730f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany}
731f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany
732f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya SerebryanyTEST(SanitizerCommon, LargeMmapAllocatorBlockBegin) {
733f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany  LargeMmapAllocator<> a;
73486277eb844c4983c81de62d7c050e92fe7155788Stephen Hines  a.Init(/* may_return_null */ false);
735f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany  AllocatorStats stats;
736f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany  stats.Init();
737f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany
738f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany  static const uptr kNumAllocs = 1024;
739f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany  static const uptr kNumExpectedFalseLookups = 10000000;
740f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany  char *allocated[kNumAllocs];
741f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany  static const uptr size = 4096;
742f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany  // Allocate some.
743f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany  for (uptr i = 0; i < kNumAllocs; i++) {
744f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany    allocated[i] = (char *)a.Allocate(&stats, size, 1);
745f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany  }
746f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany
7478fa4edcb169ab77355c77e065fc5387085787a8aKostya Serebryany  a.ForceLock();
748f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany  for (uptr i = 0; i < kNumAllocs  * kNumAllocs; i++) {
749f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany    // if ((i & (i - 1)) == 0) fprintf(stderr, "[%zd]\n", i);
750f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany    char *p1 = allocated[i % kNumAllocs];
7514fcc565018922bc50bd07858152e772bf642d5bbSergey Matveev    EXPECT_EQ(p1, a.GetBlockBeginFastLocked(p1));
7524fcc565018922bc50bd07858152e772bf642d5bbSergey Matveev    EXPECT_EQ(p1, a.GetBlockBeginFastLocked(p1 + size / 2));
7534fcc565018922bc50bd07858152e772bf642d5bbSergey Matveev    EXPECT_EQ(p1, a.GetBlockBeginFastLocked(p1 + size - 1));
7544fcc565018922bc50bd07858152e772bf642d5bbSergey Matveev    EXPECT_EQ(p1, a.GetBlockBeginFastLocked(p1 - 100));
755f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany  }
756f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany
757f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany  for (uptr i = 0; i < kNumExpectedFalseLookups; i++) {
758f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany    void *p = reinterpret_cast<void *>(i % 1024);
7594fcc565018922bc50bd07858152e772bf642d5bbSergey Matveev    EXPECT_EQ((void *)0, a.GetBlockBeginFastLocked(p));
760f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany    p = reinterpret_cast<void *>(~0L - (i % 1024));
7614fcc565018922bc50bd07858152e772bf642d5bbSergey Matveev    EXPECT_EQ((void *)0, a.GetBlockBeginFastLocked(p));
762f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany  }
7638fa4edcb169ab77355c77e065fc5387085787a8aKostya Serebryany  a.ForceUnlock();
764f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany
765f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany  for (uptr i = 0; i < kNumAllocs; i++)
766f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany    a.Deallocate(&stats, allocated[i]);
767300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany}
768300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
769f8c3f3db72780cd57ce7959e70167b7553e55fb8Kostya Serebryany
77086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#if SANITIZER_CAN_USE_ALLOCATOR64
771f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev// Regression test for out-of-memory condition in PopulateFreeList().
772f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey MatveevTEST(SanitizerCommon, SizeClassAllocator64PopulateFreeListOOM) {
773f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  // In a world where regions are small and chunks are huge...
774f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  typedef SizeClassMap<63, 128, 16> SpecialSizeClassMap;
775f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, 0,
776f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev                               SpecialSizeClassMap> SpecialAllocator64;
777f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  const uptr kRegionSize =
778f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev      kAllocatorSize / SpecialSizeClassMap::kNumClassesRounded;
779f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  SpecialAllocator64 *a = new SpecialAllocator64;
780f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  a->Init();
781f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  SizeClassAllocatorLocalCache<SpecialAllocator64> cache;
782f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  memset(&cache, 0, sizeof(cache));
783f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  cache.Init(0);
784f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev
785f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  // ...one man is on a mission to overflow a region with a series of
786f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  // successive allocations.
787f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  const uptr kClassID = 107;
788f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  const uptr kAllocationSize = DefaultSizeClassMap::Size(kClassID);
789f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  ASSERT_LT(2 * kAllocationSize, kRegionSize);
790f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  ASSERT_GT(3 * kAllocationSize, kRegionSize);
791f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  cache.Allocate(a, kClassID);
792f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  EXPECT_DEATH(cache.Allocate(a, kClassID) && cache.Allocate(a, kClassID),
793f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev               "The process has exhausted");
794f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  a->TestOnlyUnmap();
795f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  delete a;
796f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev}
797f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev#endif
798f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev
7992d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesTEST(SanitizerCommon, TwoLevelByteMap) {
8002d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  const u64 kSize1 = 1 << 6, kSize2 = 1 << 12;
8012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  const u64 n = kSize1 * kSize2;
8022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  TwoLevelByteMap<kSize1, kSize2> m;
8032d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  m.TestOnlyInit();
8042d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  for (u64 i = 0; i < n; i += 7) {
8052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    m.set(i, (i % 100) + 1);
8062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
8072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  for (u64 j = 0; j < n; j++) {
8082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    if (j % 7)
8092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      EXPECT_EQ(m[j], 0);
8102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    else
8112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines      EXPECT_EQ(m[j], (j % 100) + 1);
8122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
8132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
8142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  m.TestOnlyUnmap();
8152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
8162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
8172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
8182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestypedef TwoLevelByteMap<1 << 12, 1 << 13, TestMapUnmapCallback> TestByteMap;
8192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
8202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstruct TestByteMapParam {
8212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  TestByteMap *m;
8222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  size_t shard;
8232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  size_t num_shards;
8242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines};
8252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
8262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid *TwoLevelByteMapUserThread(void *param) {
8272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  TestByteMapParam *p = (TestByteMapParam*)param;
8282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  for (size_t i = p->shard; i < p->m->size(); i += p->num_shards) {
8292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    size_t val = (i % 100) + 1;
8302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    p->m->set(i, val);
8312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    EXPECT_EQ((*p->m)[i], val);
8322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
8332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return 0;
8342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
8352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
8362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen HinesTEST(SanitizerCommon, ThreadedTwoLevelByteMap) {
8372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  TestByteMap m;
8382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  m.TestOnlyInit();
8392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  TestMapUnmapCallback::map_count = 0;
8402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  TestMapUnmapCallback::unmap_count = 0;
8412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  static const int kNumThreads = 4;
8422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  pthread_t t[kNumThreads];
8432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  TestByteMapParam p[kNumThreads];
8442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  for (int i = 0; i < kNumThreads; i++) {
8452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    p[i].m = &m;
8462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    p[i].shard = i;
8472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    p[i].num_shards = kNumThreads;
8482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    PTHREAD_CREATE(&t[i], 0, TwoLevelByteMapUserThread, &p[i]);
8492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
8502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  for (int i = 0; i < kNumThreads; i++) {
8512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    PTHREAD_JOIN(t[i], 0);
8522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  }
8532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  EXPECT_EQ((uptr)TestMapUnmapCallback::map_count, m.size1());
8542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  EXPECT_EQ((uptr)TestMapUnmapCallback::unmap_count, 0UL);
8552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  m.TestOnlyUnmap();
8562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  EXPECT_EQ((uptr)TestMapUnmapCallback::map_count, m.size1());
8572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  EXPECT_EQ((uptr)TestMapUnmapCallback::unmap_count, m.size1());
8582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
8592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
86086277eb844c4983c81de62d7c050e92fe7155788Stephen Hines#endif  // #if !SANITIZER_DEBUG
861