sanitizer_allocator_test.cc revision 374fd35926d1c4877ac26ca8e2877154cb698cb5
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
1748ddbef1d051875b2d0b204e8d78300b58d80a85Evgeniy Stepanov#include "sanitizer_test_utils.h"
1848ddbef1d051875b2d0b204e8d78300b58d80a85Evgeniy Stepanov
19225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov#include "gtest/gtest.h"
2072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
21225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov#include <stdlib.h>
229fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany#include <pthread.h>
2372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#include <algorithm>
2472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#include <vector>
25300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany#include <set>
2672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
2768902f431172d101f3c6322d96a99d705a37ad95Dmitry Vyukov// Too slow for debug build
28b6bb60b0fa39efee537cc34bc200edc976df0bc4Dmitry Vyukov#if TSAN_DEBUG == 0
2968902f431172d101f3c6322d96a99d705a37ad95Dmitry Vyukov
3072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#if SANITIZER_WORDSIZE == 64
3172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanystatic const uptr kAllocatorSpace = 0x700000000000ULL;
3272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanystatic const uptr kAllocatorSize  = 0x010000000000ULL;  // 1T.
3345595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryanystatic const u64 kAddressSpaceSize = 1ULL << 47;
3472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
3572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytypedef SizeClassAllocator64<
3672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  kAllocatorSpace, kAllocatorSize, 16, DefaultSizeClassMap> Allocator64;
3772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
3872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytypedef SizeClassAllocator64<
3972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  kAllocatorSpace, kAllocatorSize, 16, CompactSizeClassMap> Allocator64Compact;
4045595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany#else
4145595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryanystatic const u64 kAddressSpaceSize = 1ULL << 32;
4272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
4372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
4445595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryanytypedef SizeClassAllocator32<
4545595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  0, kAddressSpaceSize, 16, CompactSizeClassMap> Allocator32Compact;
4645595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany
4772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate <class SizeClassMap>
4872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid TestSizeClassMap() {
4972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  typedef SizeClassMap SCMap;
50bb5d0575f9b1100a326f125c7cd8224938af5693Kostya Serebryany  // SCMap::Print();
51038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany  SCMap::Validate();
5272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
5372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
5472166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, DefaultSizeClassMap) {
5572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassMap<DefaultSizeClassMap>();
5672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
5772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
5872166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, CompactSizeClassMap) {
5972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassMap<CompactSizeClassMap>();
6072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
6172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
6272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate <class Allocator>
6372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid TestSizeClassAllocator() {
6445595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  Allocator *a = new Allocator;
6545595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  a->Init();
66a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov  SizeClassAllocatorLocalCache<Allocator> cache;
67bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  memset(&cache, 0, sizeof(cache));
68bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  cache.Init(0);
6972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
7072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  static const uptr sizes[] = {1, 16, 30, 40, 100, 1000, 10000,
71b1f21c69e02d99944c66e0520d07d8c14d99756fKostya Serebryany    50000, 60000, 100000, 120000, 300000, 500000, 1000000, 2000000};
7272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
7372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  std::vector<void *> allocated;
7472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
7572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  uptr last_total_allocated = 0;
76b1f21c69e02d99944c66e0520d07d8c14d99756fKostya Serebryany  for (int i = 0; i < 3; i++) {
7772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    // Allocate a bunch of chunks.
7845595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany    for (uptr s = 0; s < ARRAY_SIZE(sizes); s++) {
7972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      uptr size = sizes[s];
8045595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany      if (!a->CanAllocate(size, 1)) continue;
8172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      // printf("s = %ld\n", size);
827fe5526c2cb2d88e3ab288aa601a874c47fedb69Evgeniy Stepanov      uptr n_iter = std::max((uptr)6, 8000000 / size);
83b1f21c69e02d99944c66e0520d07d8c14d99756fKostya Serebryany      // fprintf(stderr, "size: %ld iter: %ld\n", size, n_iter);
8472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      for (uptr i = 0; i < n_iter; i++) {
85a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov        uptr class_id0 = Allocator::SizeClassMapT::ClassID(size);
86a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov        char *x = (char*)cache.Allocate(a, class_id0);
87d9b740452db50b47ca16abdc0f5e4bc2abf3afa9Kostya Serebryany        x[0] = 0;
88d9b740452db50b47ca16abdc0f5e4bc2abf3afa9Kostya Serebryany        x[size - 1] = 0;
89d9b740452db50b47ca16abdc0f5e4bc2abf3afa9Kostya Serebryany        x[size / 2] = 0;
9072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        allocated.push_back(x);
918a41bdc963afdf3c2e14aad64a7cd3291fefd8cfKostya Serebryany        CHECK_EQ(x, a->GetBlockBegin(x));
92d9b740452db50b47ca16abdc0f5e4bc2abf3afa9Kostya Serebryany        CHECK_EQ(x, a->GetBlockBegin(x + size - 1));
9345595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany        CHECK(a->PointerIsMine(x));
94da1f82bcbe50b28d11e93eacdcd529e9f0e2ef38Kostya Serebryany        CHECK(a->PointerIsMine(x + size - 1));
95da1f82bcbe50b28d11e93eacdcd529e9f0e2ef38Kostya Serebryany        CHECK(a->PointerIsMine(x + size / 2));
9645595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany        CHECK_GE(a->GetActuallyAllocatedSize(x), size);
9745595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany        uptr class_id = a->GetSizeClass(x);
9872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        CHECK_EQ(class_id, Allocator::SizeClassMapT::ClassID(size));
9945595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany        uptr *metadata = reinterpret_cast<uptr*>(a->GetMetaData(x));
10072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        metadata[0] = reinterpret_cast<uptr>(x) + 1;
10172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        metadata[1] = 0xABCD;
10272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      }
10372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
10472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    // Deallocate all.
10572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (uptr i = 0; i < allocated.size(); i++) {
10672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      void *x = allocated[i];
10745595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany      uptr *metadata = reinterpret_cast<uptr*>(a->GetMetaData(x));
10872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(metadata[0], reinterpret_cast<uptr>(x) + 1);
10972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(metadata[1], 0xABCD);
110a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov      cache.Deallocate(a, a->GetSizeClass(x), x);
11172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
11272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    allocated.clear();
11345595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany    uptr total_allocated = a->TotalMemoryUsed();
11472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    if (last_total_allocated == 0)
11572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      last_total_allocated = total_allocated;
11672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_EQ(last_total_allocated, total_allocated);
11772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
11872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
119aa0f20dca32ad6ed0d4f5623b393dd700375f12aKostya Serebryany  // Check that GetBlockBegin never crashes.
120aa0f20dca32ad6ed0d4f5623b393dd700375f12aKostya Serebryany  for (uptr x = 0, step = kAddressSpaceSize / 100000;
121aa0f20dca32ad6ed0d4f5623b393dd700375f12aKostya Serebryany       x < kAddressSpaceSize - step; x += step)
122aa0f20dca32ad6ed0d4f5623b393dd700375f12aKostya Serebryany    if (a->PointerIsMine(reinterpret_cast<void *>(x)))
123aa0f20dca32ad6ed0d4f5623b393dd700375f12aKostya Serebryany      Ident(a->GetBlockBegin(reinterpret_cast<void *>(x)));
124aa0f20dca32ad6ed0d4f5623b393dd700375f12aKostya Serebryany
12545595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  a->TestOnlyUnmap();
12645595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  delete a;
12772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
12872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
12972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#if SANITIZER_WORDSIZE == 64
13072166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64) {
13172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassAllocator<Allocator64>();
13272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
13372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
13472166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64Compact) {
13572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassAllocator<Allocator64Compact>();
13672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
13772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
13872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
13945595ba6b77b54b8212389cba6b95dc634122145Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator32Compact) {
14045595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany  TestSizeClassAllocator<Allocator32Compact>();
14145595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany}
14245595ba6b77b54b8212389cba6b95dc634122145Kostya Serebryany
14372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate <class Allocator>
144784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryanyvoid SizeClassAllocatorMetadataStress() {
145784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  Allocator *a = new Allocator;
146784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  a->Init();
147a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov  SizeClassAllocatorLocalCache<Allocator> cache;
148bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  memset(&cache, 0, sizeof(cache));
149bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  cache.Init(0);
15072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
151871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany  const uptr kNumAllocs = 1 << 13;
15272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  void *allocated[kNumAllocs];
153871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany  void *meta[kNumAllocs];
15472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr i = 0; i < kNumAllocs; i++) {
155a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov    void *x = cache.Allocate(a, 1 + i % 50);
15672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    allocated[i] = x;
157871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany    meta[i] = a->GetMetaData(x);
15872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
15972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Get Metadata kNumAllocs^2 times.
16072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr i = 0; i < kNumAllocs * kNumAllocs; i++) {
161871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany    uptr idx = i % kNumAllocs;
162871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany    void *m = a->GetMetaData(allocated[idx]);
163871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany    EXPECT_EQ(m, meta[idx]);
16472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
16572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr i = 0; i < kNumAllocs; i++) {
166a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov    cache.Deallocate(a, 1 + i % 50, allocated[i]);
16772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
16872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
169784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  a->TestOnlyUnmap();
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}
181a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany#endif  // SANITIZER_WORDSIZE == 64
182784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator32CompactMetadataStress) {
183784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany  SizeClassAllocatorMetadataStress<Allocator32Compact>();
184784935d1bbc301eaf92fd9f7d3a551eb65edcd15Kostya Serebryany}
18572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
186a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryanytemplate <class Allocator>
187a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryanyvoid SizeClassAllocatorGetBlockBeginStress() {
188a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  Allocator *a = new Allocator;
189a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  a->Init();
190a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  SizeClassAllocatorLocalCache<Allocator> cache;
191a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  memset(&cache, 0, sizeof(cache));
192a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  cache.Init(0);
193a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany
194a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  uptr max_size_class = Allocator::kNumClasses - 1;
195a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  uptr size = Allocator::SizeClassMapT::Size(max_size_class);
196a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  u64 G8 = 1ULL << 33;
197871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany  // Make sure we correctly compute GetBlockBegin() w/o overflow.
198a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  for (size_t i = 0; i <= G8 / size; i++) {
199a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany    void *x = cache.Allocate(a, max_size_class);
200a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany    void *beg = a->GetBlockBegin(x);
201374fd35926d1c4877ac26ca8e2877154cb698cb5Dmitry Vyukov    // if ((i & (i - 1)) == 0)
202374fd35926d1c4877ac26ca8e2877154cb698cb5Dmitry Vyukov    //   fprintf(stderr, "[%zd] %p %p\n", i, x, beg);
203a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany    EXPECT_EQ(x, beg);
204a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  }
205a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany
206a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  a->TestOnlyUnmap();
207a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  delete a;
208a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany}
209a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany
210a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany#if SANITIZER_WORDSIZE == 64
211871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64GetBlockBegin) {
212a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany  SizeClassAllocatorGetBlockBeginStress<Allocator64>();
213a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany}
214871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64CompactGetBlockBegin) {
215871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany  SizeClassAllocatorGetBlockBeginStress<Allocator64Compact>();
216871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany}
217871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator32CompactGetBlockBegin) {
218871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany  SizeClassAllocatorGetBlockBeginStress<Allocator32Compact>();
219871b7fd4fdde47cbf36c2b5c19d679e87dd11df6Kostya Serebryany}
220a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany#endif  // SANITIZER_WORDSIZE == 64
221a1560bd5d12ddf245ca44fa6a259e9b5c5f81933Kostya Serebryany
222214621f7663896987dc509561c762460226c68c2Kostya Serebryanystruct TestMapUnmapCallback {
223214621f7663896987dc509561c762460226c68c2Kostya Serebryany  static int map_count, unmap_count;
224214621f7663896987dc509561c762460226c68c2Kostya Serebryany  void OnMap(uptr p, uptr size) const { map_count++; }
225214621f7663896987dc509561c762460226c68c2Kostya Serebryany  void OnUnmap(uptr p, uptr size) const { unmap_count++; }
226214621f7663896987dc509561c762460226c68c2Kostya Serebryany};
227214621f7663896987dc509561c762460226c68c2Kostya Serebryanyint TestMapUnmapCallback::map_count;
228214621f7663896987dc509561c762460226c68c2Kostya Serebryanyint TestMapUnmapCallback::unmap_count;
229214621f7663896987dc509561c762460226c68c2Kostya Serebryany
230214621f7663896987dc509561c762460226c68c2Kostya Serebryany#if SANITIZER_WORDSIZE == 64
231214621f7663896987dc509561c762460226c68c2Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64MapUnmapCallback) {
232214621f7663896987dc509561c762460226c68c2Kostya Serebryany  TestMapUnmapCallback::map_count = 0;
233214621f7663896987dc509561c762460226c68c2Kostya Serebryany  TestMapUnmapCallback::unmap_count = 0;
234214621f7663896987dc509561c762460226c68c2Kostya Serebryany  typedef SizeClassAllocator64<
235214621f7663896987dc509561c762460226c68c2Kostya Serebryany      kAllocatorSpace, kAllocatorSize, 16, DefaultSizeClassMap,
236214621f7663896987dc509561c762460226c68c2Kostya Serebryany      TestMapUnmapCallback> Allocator64WithCallBack;
237214621f7663896987dc509561c762460226c68c2Kostya Serebryany  Allocator64WithCallBack *a = new Allocator64WithCallBack;
238214621f7663896987dc509561c762460226c68c2Kostya Serebryany  a->Init();
239214621f7663896987dc509561c762460226c68c2Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::map_count, 1);  // Allocator state.
240a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov  SizeClassAllocatorLocalCache<Allocator64WithCallBack> cache;
241bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  memset(&cache, 0, sizeof(cache));
242bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  cache.Init(0);
243bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  AllocatorStats stats;
244bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  stats.Init();
245f2c417c3b7d7a11f1f6f20edca08af2cb1fad142Kostya Serebryany  a->AllocateBatch(&stats, &cache, 32);
246567ad078d73babb2c8addfbebb1ddd6cd0085c53Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::map_count, 3);  // State + alloc + metadata.
247214621f7663896987dc509561c762460226c68c2Kostya Serebryany  a->TestOnlyUnmap();
248214621f7663896987dc509561c762460226c68c2Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::unmap_count, 1);  // The whole thing.
249214621f7663896987dc509561c762460226c68c2Kostya Serebryany  delete a;
250214621f7663896987dc509561c762460226c68c2Kostya Serebryany}
251214621f7663896987dc509561c762460226c68c2Kostya Serebryany#endif
252214621f7663896987dc509561c762460226c68c2Kostya Serebryany
253214621f7663896987dc509561c762460226c68c2Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator32MapUnmapCallback) {
254214621f7663896987dc509561c762460226c68c2Kostya Serebryany  TestMapUnmapCallback::map_count = 0;
255214621f7663896987dc509561c762460226c68c2Kostya Serebryany  TestMapUnmapCallback::unmap_count = 0;
256214621f7663896987dc509561c762460226c68c2Kostya Serebryany  typedef SizeClassAllocator32<
257214621f7663896987dc509561c762460226c68c2Kostya Serebryany      0, kAddressSpaceSize, 16, CompactSizeClassMap,
258214621f7663896987dc509561c762460226c68c2Kostya Serebryany      TestMapUnmapCallback> Allocator32WithCallBack;
259214621f7663896987dc509561c762460226c68c2Kostya Serebryany  Allocator32WithCallBack *a = new Allocator32WithCallBack;
260214621f7663896987dc509561c762460226c68c2Kostya Serebryany  a->Init();
261214621f7663896987dc509561c762460226c68c2Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::map_count, 1);  // Allocator state.
262a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov  SizeClassAllocatorLocalCache<Allocator32WithCallBack>  cache;
263bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  memset(&cache, 0, sizeof(cache));
264bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  cache.Init(0);
265bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  AllocatorStats stats;
266bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  stats.Init();
267f2c417c3b7d7a11f1f6f20edca08af2cb1fad142Kostya Serebryany  a->AllocateBatch(&stats, &cache, 32);
268214621f7663896987dc509561c762460226c68c2Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::map_count, 2);  // alloc.
269214621f7663896987dc509561c762460226c68c2Kostya Serebryany  a->TestOnlyUnmap();
270214621f7663896987dc509561c762460226c68c2Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::unmap_count, 2);  // The whole thing + alloc.
271214621f7663896987dc509561c762460226c68c2Kostya Serebryany  delete a;
272ca661f51dbccc8b8bdeb308751f3b160501f7954Dmitry Vyukov  // fprintf(stderr, "Map: %d Unmap: %d\n",
273ca661f51dbccc8b8bdeb308751f3b160501f7954Dmitry Vyukov  //         TestMapUnmapCallback::map_count,
274ca661f51dbccc8b8bdeb308751f3b160501f7954Dmitry Vyukov  //         TestMapUnmapCallback::unmap_count);
275214621f7663896987dc509561c762460226c68c2Kostya Serebryany}
276214621f7663896987dc509561c762460226c68c2Kostya Serebryany
277214621f7663896987dc509561c762460226c68c2Kostya SerebryanyTEST(SanitizerCommon, LargeMmapAllocatorMapUnmapCallback) {
278214621f7663896987dc509561c762460226c68c2Kostya Serebryany  TestMapUnmapCallback::map_count = 0;
279214621f7663896987dc509561c762460226c68c2Kostya Serebryany  TestMapUnmapCallback::unmap_count = 0;
280214621f7663896987dc509561c762460226c68c2Kostya Serebryany  LargeMmapAllocator<TestMapUnmapCallback> a;
281214621f7663896987dc509561c762460226c68c2Kostya Serebryany  a.Init();
282bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  AllocatorStats stats;
283bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  stats.Init();
284bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  void *x = a.Allocate(&stats, 1 << 20, 1);
285214621f7663896987dc509561c762460226c68c2Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::map_count, 1);
286bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  a.Deallocate(&stats, x);
287214621f7663896987dc509561c762460226c68c2Kostya Serebryany  EXPECT_EQ(TestMapUnmapCallback::unmap_count, 1);
288214621f7663896987dc509561c762460226c68c2Kostya Serebryany}
289214621f7663896987dc509561c762460226c68c2Kostya Serebryany
29072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate<class Allocator>
29172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid FailInAssertionOnOOM() {
29272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  Allocator a;
29372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  a.Init();
294a343ca04767218fd05dd9557ed4d180b55b7fb11Dmitry Vyukov  SizeClassAllocatorLocalCache<Allocator> cache;
295bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  memset(&cache, 0, sizeof(cache));
296bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  cache.Init(0);
297bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  AllocatorStats stats;
298bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  stats.Init();
29972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < 1000000; i++) {
300f2c417c3b7d7a11f1f6f20edca08af2cb1fad142Kostya Serebryany    a.AllocateBatch(&stats, &cache, 52);
30172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
30272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
30372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  a.TestOnlyUnmap();
30472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
30572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
30672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#if SANITIZER_WORDSIZE == 64
30772166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64Overflow) {
30872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  EXPECT_DEATH(FailInAssertionOnOOM<Allocator64>(), "Out of memory");
30972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
31072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
31172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
31272166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, LargeMmapAllocator) {
313214621f7663896987dc509561c762460226c68c2Kostya Serebryany  LargeMmapAllocator<> a;
31472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  a.Init();
315bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  AllocatorStats stats;
316bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  stats.Init();
31772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
318b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany  static const int kNumAllocs = 1000;
319da1f82bcbe50b28d11e93eacdcd529e9f0e2ef38Kostya Serebryany  char *allocated[kNumAllocs];
320b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany  static const uptr size = 4000;
32172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Allocate some.
32272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < kNumAllocs; i++) {
323bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov    allocated[i] = (char *)a.Allocate(&stats, size, 1);
324b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany    CHECK(a.PointerIsMine(allocated[i]));
32572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
32672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Deallocate all.
32772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  CHECK_GT(a.TotalMemoryUsed(), size * kNumAllocs);
32872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < kNumAllocs; i++) {
329da1f82bcbe50b28d11e93eacdcd529e9f0e2ef38Kostya Serebryany    char *p = allocated[i];
33072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK(a.PointerIsMine(p));
331bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov    a.Deallocate(&stats, p);
33272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
33372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Check that non left.
33472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  CHECK_EQ(a.TotalMemoryUsed(), 0);
33572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
33672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Allocate some more, also add metadata.
33772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < kNumAllocs; i++) {
338bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov    char *x = (char *)a.Allocate(&stats, size, 1);
33972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_GE(a.GetActuallyAllocatedSize(x), size);
34072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    uptr *meta = reinterpret_cast<uptr*>(a.GetMetaData(x));
34172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    *meta = i;
34272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    allocated[i] = x;
34372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
344b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany  for (int i = 0; i < kNumAllocs * kNumAllocs; i++) {
345b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany    char *p = allocated[i % kNumAllocs];
346b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany    CHECK(a.PointerIsMine(p));
347b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany    CHECK(a.PointerIsMine(p + 2000));
348b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany  }
34972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  CHECK_GT(a.TotalMemoryUsed(), size * kNumAllocs);
35072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  // Deallocate all in reverse order.
35172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (int i = 0; i < kNumAllocs; i++) {
35272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    int idx = kNumAllocs - i - 1;
353da1f82bcbe50b28d11e93eacdcd529e9f0e2ef38Kostya Serebryany    char *p = allocated[idx];
35472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    uptr *meta = reinterpret_cast<uptr*>(a.GetMetaData(p));
35572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK_EQ(*meta, idx);
35672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    CHECK(a.PointerIsMine(p));
357bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov    a.Deallocate(&stats, p);
35872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
35972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  CHECK_EQ(a.TotalMemoryUsed(), 0);
360b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany
361b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany  // Test alignments.
36272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  uptr max_alignment = SANITIZER_WORDSIZE == 64 ? (1 << 28) : (1 << 24);
36372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr alignment = 8; alignment <= max_alignment; alignment *= 2) {
364b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany    const uptr kNumAlignedAllocs = 100;
36568d3a1bae35be595faf7d9f028a268f390501029Kostya Serebryany    for (uptr i = 0; i < kNumAlignedAllocs; i++) {
36672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      uptr size = ((i % 10) + 1) * 4096;
367bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov      char *p = allocated[i] = (char *)a.Allocate(&stats, size, alignment);
368da1f82bcbe50b28d11e93eacdcd529e9f0e2ef38Kostya Serebryany      CHECK_EQ(p, a.GetBlockBegin(p));
369da1f82bcbe50b28d11e93eacdcd529e9f0e2ef38Kostya Serebryany      CHECK_EQ(p, a.GetBlockBegin(p + size - 1));
370da1f82bcbe50b28d11e93eacdcd529e9f0e2ef38Kostya Serebryany      CHECK_EQ(p, a.GetBlockBegin(p + size / 2));
37172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(0, (uptr)allocated[i] % alignment);
37272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      p[0] = p[size - 1] = 0;
37372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
37468d3a1bae35be595faf7d9f028a268f390501029Kostya Serebryany    for (uptr i = 0; i < kNumAlignedAllocs; i++) {
375bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov      a.Deallocate(&stats, allocated[i]);
37672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
37772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
378a2c1d98745a9e8e860948004423d0072424f48b7Kostya Serebryany
379a2c1d98745a9e8e860948004423d0072424f48b7Kostya Serebryany  // Regression test for boundary condition in GetBlockBegin().
380a2c1d98745a9e8e860948004423d0072424f48b7Kostya Serebryany  uptr page_size = GetPageSizeCached();
381a2c1d98745a9e8e860948004423d0072424f48b7Kostya Serebryany  char *p = (char *)a.Allocate(&stats, page_size, 1);
382a2c1d98745a9e8e860948004423d0072424f48b7Kostya Serebryany  CHECK_EQ(p, a.GetBlockBegin(p));
383a2c1d98745a9e8e860948004423d0072424f48b7Kostya Serebryany  CHECK_EQ(p, (char *)a.GetBlockBegin(p + page_size - 1));
384a2c1d98745a9e8e860948004423d0072424f48b7Kostya Serebryany  CHECK_NE(p, (char *)a.GetBlockBegin(p + page_size));
385a2c1d98745a9e8e860948004423d0072424f48b7Kostya Serebryany  a.Deallocate(&stats, p);
38672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
38772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
38872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate
38972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany<class PrimaryAllocator, class SecondaryAllocator, class AllocatorCache>
39072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid TestCombinedAllocator() {
391674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  typedef
392674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      CombinedAllocator<PrimaryAllocator, AllocatorCache, SecondaryAllocator>
393674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      Allocator;
394674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  Allocator *a = new Allocator;
395674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  a->Init();
39672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
39772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  AllocatorCache cache;
398bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  memset(&cache, 0, sizeof(cache));
399bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  a->InitCache(&cache);
40072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
401674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  EXPECT_EQ(a->Allocate(&cache, -1, 1), (void*)0);
402674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  EXPECT_EQ(a->Allocate(&cache, -1, 1024), (void*)0);
403674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  EXPECT_EQ(a->Allocate(&cache, (uptr)-1 - 1024, 1), (void*)0);
404674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  EXPECT_EQ(a->Allocate(&cache, (uptr)-1 - 1024, 1024), (void*)0);
405674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  EXPECT_EQ(a->Allocate(&cache, (uptr)-1 - 1023, 1024), (void*)0);
40672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
40772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const uptr kNumAllocs = 100000;
40872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const uptr kNumIter = 10;
40972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  for (uptr iter = 0; iter < kNumIter; iter++) {
41072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    std::vector<void*> allocated;
41172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (uptr i = 0; i < kNumAllocs; i++) {
41272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      uptr size = (i % (1 << 14)) + 1;
41372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      if ((i % 1024) == 0)
41472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany        size = 1 << (10 + (i % 14));
415674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      void *x = a->Allocate(&cache, size, 1);
416674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      uptr *meta = reinterpret_cast<uptr*>(a->GetMetaData(x));
41772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_EQ(*meta, 0);
41872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      *meta = size;
41972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      allocated.push_back(x);
42072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
42172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
42272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    random_shuffle(allocated.begin(), allocated.end());
42372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
42472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    for (uptr i = 0; i < kNumAllocs; i++) {
42572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      void *x = allocated[i];
426674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      uptr *meta = reinterpret_cast<uptr*>(a->GetMetaData(x));
42772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      CHECK_NE(*meta, 0);
428674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      CHECK(a->PointerIsMine(x));
42972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      *meta = 0;
430674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      a->Deallocate(&cache, x);
43172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
43272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    allocated.clear();
433674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany    a->SwallowCache(&cache);
43472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
435bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  a->DestroyCache(&cache);
436674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  a->TestOnlyUnmap();
43772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
43872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
43972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#if SANITIZER_WORDSIZE == 64
440674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya SerebryanyTEST(SanitizerCommon, CombinedAllocator64) {
44172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestCombinedAllocator<Allocator64,
442214621f7663896987dc509561c762460226c68c2Kostya Serebryany      LargeMmapAllocator<>,
44372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      SizeClassAllocatorLocalCache<Allocator64> > ();
44472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
445674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany
446674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya SerebryanyTEST(SanitizerCommon, CombinedAllocator64Compact) {
447674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  TestCombinedAllocator<Allocator64Compact,
448214621f7663896987dc509561c762460226c68c2Kostya Serebryany      LargeMmapAllocator<>,
449674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      SizeClassAllocatorLocalCache<Allocator64Compact> > ();
450674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany}
45172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
45272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
453674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya SerebryanyTEST(SanitizerCommon, CombinedAllocator32Compact) {
454674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany  TestCombinedAllocator<Allocator32Compact,
455214621f7663896987dc509561c762460226c68c2Kostya Serebryany      LargeMmapAllocator<>,
456674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany      SizeClassAllocatorLocalCache<Allocator32Compact> > ();
457674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany}
458674d05c15d3cfcd2e9f0e9fde47d25cd69af924bKostya Serebryany
45972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanytemplate <class AllocatorCache>
46072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryanyvoid TestSizeClassAllocatorLocalCache() {
46172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  AllocatorCache cache;
462e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  typedef typename AllocatorCache::Allocator Allocator;
463e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  Allocator *a = new Allocator();
46472166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
465e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  a->Init();
466bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  memset(&cache, 0, sizeof(cache));
467bdd844cb41718c27ef727a99a236191bc29a3df8Dmitry Vyukov  cache.Init(0);
46872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
46972166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const uptr kNumAllocs = 10000;
47072166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  const int kNumIter = 100;
47172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  uptr saved_total = 0;
472038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany  for (int class_id = 1; class_id <= 5; class_id++) {
473b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany    for (int it = 0; it < kNumIter; it++) {
474038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany      void *allocated[kNumAllocs];
475038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany      for (uptr i = 0; i < kNumAllocs; i++) {
476038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany        allocated[i] = cache.Allocate(a, class_id);
477038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany      }
478038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany      for (uptr i = 0; i < kNumAllocs; i++) {
479038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany        cache.Deallocate(a, class_id, allocated[i]);
480038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany      }
481038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany      cache.Drain(a);
482038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany      uptr total_allocated = a->TotalMemoryUsed();
483b8c363d3087128a05b18bbcf5ce0942607e34396Kostya Serebryany      if (it)
484038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany        CHECK_EQ(saved_total, total_allocated);
485038820fbab7e77c546b2c37bf674824980320f18Kostya Serebryany      saved_total = total_allocated;
48672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany    }
48772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  }
48872166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
489e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  a->TestOnlyUnmap();
490e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  delete a;
49172166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
49272166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany
49372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#if SANITIZER_WORDSIZE == 64
49472166ca99c2f8898a7a540e60aac3959cbd959bfKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64LocalCache) {
49572166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany  TestSizeClassAllocatorLocalCache<
49672166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany      SizeClassAllocatorLocalCache<Allocator64> >();
49772166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany}
498e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany
499e280ce59d37a67bee14da56a22e205d6562530b0Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64CompactLocalCache) {
500e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  TestSizeClassAllocatorLocalCache<
501e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany      SizeClassAllocatorLocalCache<Allocator64Compact> >();
502e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany}
50372166ca99c2f8898a7a540e60aac3959cbd959bfKostya Serebryany#endif
504225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov
505e280ce59d37a67bee14da56a22e205d6562530b0Kostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator32CompactLocalCache) {
506e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany  TestSizeClassAllocatorLocalCache<
507e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany      SizeClassAllocatorLocalCache<Allocator32Compact> >();
508e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany}
509e280ce59d37a67bee14da56a22e205d6562530b0Kostya Serebryany
5109fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany#if SANITIZER_WORDSIZE == 64
5119fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryanytypedef SizeClassAllocatorLocalCache<Allocator64> AllocatorCache;
5120d02d75ca1e34217cb762ec2b5cc13a88993ba94Evgeniy Stepanovstatic AllocatorCache static_allocator_cache;
5139fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany
5149fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryanyvoid *AllocatorLeakTestWorker(void *arg) {
5159fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  typedef AllocatorCache::Allocator Allocator;
5169fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  Allocator *a = (Allocator*)(arg);
5179fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  static_allocator_cache.Allocate(a, 10);
5189fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  static_allocator_cache.Drain(a);
5199fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  return 0;
5209fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany}
5219fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany
5229fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya SerebryanyTEST(SanitizerCommon, AllocatorLeakTest) {
52368acb909db275a9d4fb16b37fab4c42b72671abbAlexey Samsonov  typedef AllocatorCache::Allocator Allocator;
5249fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  Allocator a;
5259fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  a.Init();
5269fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  uptr total_used_memory = 0;
5279fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  for (int i = 0; i < 100; i++) {
5289fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany    pthread_t t;
5299fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany    EXPECT_EQ(0, pthread_create(&t, 0, AllocatorLeakTestWorker, &a));
5309fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany    EXPECT_EQ(0, pthread_join(t, 0));
5319fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany    if (i == 0)
5329fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany      total_used_memory = a.TotalMemoryUsed();
5339fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany    EXPECT_EQ(a.TotalMemoryUsed(), total_used_memory);
5349fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  }
5359fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany
5369fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany  a.TestOnlyUnmap();
5379fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany}
5385d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner
5395d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner// Struct which is allocated to pass info to new threads.  The new thread frees
5405d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner// it.
5415d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Klecknerstruct NewThreadParams {
5425d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  AllocatorCache *thread_cache;
5435d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  AllocatorCache::Allocator *allocator;
5445d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  uptr class_id;
5455d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner};
5465d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner
5475d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner// Called in a new thread.  Just frees its argument.
5485d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Klecknerstatic void *DeallocNewThreadWorker(void *arg) {
5495d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  NewThreadParams *params = reinterpret_cast<NewThreadParams*>(arg);
5505d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  params->thread_cache->Deallocate(params->allocator, params->class_id, params);
5515d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  return NULL;
5525d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner}
5535d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner
5545d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner// The allocator cache is supposed to be POD and zero initialized.  We should be
5555d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner// able to call Deallocate on a zeroed cache, and it will self-initialize.
5565d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid KlecknerTEST(Allocator, AllocatorCacheDeallocNewThread) {
5575d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  AllocatorCache::Allocator allocator;
5585d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  allocator.Init();
5595d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  AllocatorCache main_cache;
5605d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  AllocatorCache child_cache;
5615d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  memset(&main_cache, 0, sizeof(main_cache));
5625d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  memset(&child_cache, 0, sizeof(child_cache));
5635d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner
5645d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  uptr class_id = DefaultSizeClassMap::ClassID(sizeof(NewThreadParams));
5655d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  NewThreadParams *params = reinterpret_cast<NewThreadParams*>(
5665d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner      main_cache.Allocate(&allocator, class_id));
5675d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  params->thread_cache = &child_cache;
5685d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  params->allocator = &allocator;
5695d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  params->class_id = class_id;
5705d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  pthread_t t;
5715d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner  EXPECT_EQ(0, pthread_create(&t, 0, DeallocNewThreadWorker, params));
5723c27d7f4e3413dd4f2e50eebac7c8f9bd916c1caReid Kleckner  EXPECT_EQ(0, pthread_join(t, 0));
5735d3dcb8fa4947ebeab61bcf512ab352576d0fb41Reid Kleckner}
5749fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany#endif
5759fc1f27f55a4bb3d54858cfd3c32d0bb11002db2Kostya Serebryany
576225f53194082f475a5d21780344ff79a2a387c13Dmitry VyukovTEST(Allocator, Basic) {
577225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  char *p = (char*)InternalAlloc(10);
578225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  EXPECT_NE(p, (char*)0);
579225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  char *p2 = (char*)InternalAlloc(20);
580225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  EXPECT_NE(p2, (char*)0);
581225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  EXPECT_NE(p2, p);
582225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  InternalFree(p);
583225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  InternalFree(p2);
584225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov}
585225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov
586225f53194082f475a5d21780344ff79a2a387c13Dmitry VyukovTEST(Allocator, Stress) {
587225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  const int kCount = 1000;
588225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  char *ptrs[kCount];
589225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  unsigned rnd = 42;
590225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  for (int i = 0; i < kCount; i++) {
59148ddbef1d051875b2d0b204e8d78300b58d80a85Evgeniy Stepanov    uptr sz = my_rand_r(&rnd) % 1000;
592225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov    char *p = (char*)InternalAlloc(sz);
593225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov    EXPECT_NE(p, (char*)0);
594225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov    ptrs[i] = p;
595225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  }
596225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  for (int i = 0; i < kCount; i++) {
597225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov    InternalFree(ptrs[i]);
598225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov  }
599225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov}
600225f53194082f475a5d21780344ff79a2a387c13Dmitry Vyukov
6016611abe0c2737a37c1c69f0527a35bb34875221dAlexey SamsonovTEST(Allocator, ScopedBuffer) {
6026611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  const int kSize = 512;
6036611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  {
6046611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov    InternalScopedBuffer<int> int_buf(kSize);
6056611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov    EXPECT_EQ(sizeof(int) * kSize, int_buf.size());  // NOLINT
6066611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  }
6076611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  InternalScopedBuffer<char> char_buf(kSize);
6086611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  EXPECT_EQ(sizeof(char) * kSize, char_buf.size());  // NOLINT
6090bb6e5ddbb11565dfe0a71b0936f0dd76251ea78Kostya Serebryany  internal_memset(char_buf.data(), 'c', kSize);
6106611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  for (int i = 0; i < kSize; i++) {
6116611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov    EXPECT_EQ('c', char_buf[i]);
6126611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov  }
6136611abe0c2737a37c1c69f0527a35bb34875221dAlexey Samsonov}
61468902f431172d101f3c6322d96a99d705a37ad95Dmitry Vyukov
615300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryanyclass IterationTestCallback {
616300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany public:
617300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  explicit IterationTestCallback(std::set<void *> *chunks)
618300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    : chunks_(chunks) {}
619300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  void operator()(void *chunk) const {
620300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    chunks_->insert(chunk);
621300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  }
622300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany private:
623300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  std::set<void *> *chunks_;
624300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany};
625300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
626300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryanytemplate <class Allocator>
627300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryanyvoid TestSizeClassAllocatorIteration() {
628300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  Allocator *a = new Allocator;
629300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  a->Init();
630300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  SizeClassAllocatorLocalCache<Allocator> cache;
631300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  memset(&cache, 0, sizeof(cache));
632300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  cache.Init(0);
633300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
634300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  static const uptr sizes[] = {1, 16, 30, 40, 100, 1000, 10000,
635300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    50000, 60000, 100000, 120000, 300000, 500000, 1000000, 2000000};
636300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
637300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  std::vector<void *> allocated;
638300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
639300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  // Allocate a bunch of chunks.
640300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  for (uptr s = 0; s < ARRAY_SIZE(sizes); s++) {
641300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    uptr size = sizes[s];
642300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    if (!a->CanAllocate(size, 1)) continue;
643300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    // printf("s = %ld\n", size);
644300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    uptr n_iter = std::max((uptr)6, 80000 / size);
645300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    // fprintf(stderr, "size: %ld iter: %ld\n", size, n_iter);
646300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    for (uptr j = 0; j < n_iter; j++) {
647300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany      uptr class_id0 = Allocator::SizeClassMapT::ClassID(size);
648300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany      void *x = cache.Allocate(a, class_id0);
649300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany      allocated.push_back(x);
650300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    }
651300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  }
652300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
653300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  std::set<void *> reported_chunks;
654300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  IterationTestCallback callback(&reported_chunks);
655300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  a->ForceLock();
6565d177a0d5973e863781b1262ece49a5e3325ecabAlexey Samsonov  a->ForEachChunk(callback);
657300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  a->ForceUnlock();
658300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
659300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  for (uptr i = 0; i < allocated.size(); i++) {
660300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    // Don't use EXPECT_NE. Reporting the first mismatch is enough.
661300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    ASSERT_NE(reported_chunks.find(allocated[i]), reported_chunks.end());
662300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  }
663300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
664300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  a->TestOnlyUnmap();
665300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  delete a;
666300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany}
667300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
668300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany#if SANITIZER_WORDSIZE == 64
669300f9534eeed62339eb8b73722d4142c60238ffcKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator64Iteration) {
670300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  TestSizeClassAllocatorIteration<Allocator64>();
671300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany}
672300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany#endif
673300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
674300f9534eeed62339eb8b73722d4142c60238ffcKostya SerebryanyTEST(SanitizerCommon, SizeClassAllocator32Iteration) {
675300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  TestSizeClassAllocatorIteration<Allocator32Compact>();
676300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany}
677300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
678300f9534eeed62339eb8b73722d4142c60238ffcKostya SerebryanyTEST(SanitizerCommon, LargeMmapAllocatorIteration) {
679300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  LargeMmapAllocator<> a;
680300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  a.Init();
681300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  AllocatorStats stats;
682300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  stats.Init();
683300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
6846c876e428923295706f63fee68ef35d2f0fbaec5Kostya Serebryany  static const uptr kNumAllocs = 1000;
685300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  char *allocated[kNumAllocs];
686300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  static const uptr size = 40;
687300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  // Allocate some.
6886c876e428923295706f63fee68ef35d2f0fbaec5Kostya Serebryany  for (uptr i = 0; i < kNumAllocs; i++) {
689300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    allocated[i] = (char *)a.Allocate(&stats, size, 1);
690300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  }
691300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
692300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  std::set<void *> reported_chunks;
693300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  IterationTestCallback callback(&reported_chunks);
694300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  a.ForceLock();
6955d177a0d5973e863781b1262ece49a5e3325ecabAlexey Samsonov  a.ForEachChunk(callback);
696300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  a.ForceUnlock();
697300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
698300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  for (uptr i = 0; i < kNumAllocs; i++) {
699300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    // Don't use EXPECT_NE. Reporting the first mismatch is enough.
700300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany    ASSERT_NE(reported_chunks.find(allocated[i]), reported_chunks.end());
701300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany  }
702300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany}
703300f9534eeed62339eb8b73722d4142c60238ffcKostya Serebryany
704f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev#if SANITIZER_WORDSIZE == 64
705f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev// Regression test for out-of-memory condition in PopulateFreeList().
706f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey MatveevTEST(SanitizerCommon, SizeClassAllocator64PopulateFreeListOOM) {
707f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  // In a world where regions are small and chunks are huge...
708f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  typedef SizeClassMap<63, 128, 16> SpecialSizeClassMap;
709f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  typedef SizeClassAllocator64<kAllocatorSpace, kAllocatorSize, 0,
710f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev                               SpecialSizeClassMap> SpecialAllocator64;
711f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  const uptr kRegionSize =
712f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev      kAllocatorSize / SpecialSizeClassMap::kNumClassesRounded;
713f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  SpecialAllocator64 *a = new SpecialAllocator64;
714f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  a->Init();
715f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  SizeClassAllocatorLocalCache<SpecialAllocator64> cache;
716f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  memset(&cache, 0, sizeof(cache));
717f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  cache.Init(0);
718f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev
719f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  // ...one man is on a mission to overflow a region with a series of
720f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  // successive allocations.
721f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  const uptr kClassID = 107;
722f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  const uptr kAllocationSize = DefaultSizeClassMap::Size(kClassID);
723f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  ASSERT_LT(2 * kAllocationSize, kRegionSize);
724f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  ASSERT_GT(3 * kAllocationSize, kRegionSize);
725f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  cache.Allocate(a, kClassID);
726f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  EXPECT_DEATH(cache.Allocate(a, kClassID) && cache.Allocate(a, kClassID),
727f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev               "The process has exhausted");
728f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  a->TestOnlyUnmap();
729f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev  delete a;
730f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev}
731f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev#endif
732f14ef72c52673c8c37c95b07fcc79631a10d7772Sergey Matveev
73368902f431172d101f3c6322d96a99d705a37ad95Dmitry Vyukov#endif  // #if TSAN_DEBUG==0
734