]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/scudo/scudo_allocator.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / scudo / scudo_allocator.h
1 //===-- scudo_allocator.h ---------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// Header for scudo_allocator.cpp.
11 ///
12 //===----------------------------------------------------------------------===//
13
14 #ifndef SCUDO_ALLOCATOR_H_
15 #define SCUDO_ALLOCATOR_H_
16
17 #include "scudo_platform.h"
18
19 namespace __scudo {
20
21 enum AllocType : u8 {
22   FromMalloc    = 0,  // Memory block came from malloc, realloc, calloc, etc.
23   FromNew       = 1,  // Memory block came from operator new.
24   FromNewArray  = 2,  // Memory block came from operator new [].
25   FromMemalign  = 3,  // Memory block came from memalign, posix_memalign, etc.
26 };
27
28 enum ChunkState : u8 {
29   ChunkAvailable  = 0,
30   ChunkAllocated  = 1,
31   ChunkQuarantine = 2
32 };
33
34 // Our header requires 64 bits of storage. Having the offset saves us from
35 // using functions such as GetBlockBegin, that is fairly costly. Our first
36 // implementation used the MetaData as well, which offers the advantage of
37 // being stored away from the chunk itself, but accessing it was costly as
38 // well. The header will be atomically loaded and stored.
39 typedef u64 PackedHeader;
40 struct UnpackedHeader {
41   u64 Checksum          : 16;
42   u64 ClassId           : 8;
43   u64 SizeOrUnusedBytes : 20;  // Size for Primary backed allocations, amount of
44                                // unused bytes in the chunk for Secondary ones.
45   u64 State             : 2;   // available, allocated, or quarantined
46   u64 AllocType         : 2;   // malloc, new, new[], or memalign
47   u64 Offset            : 16;  // Offset from the beginning of the backend
48                                // allocation to the beginning of the chunk
49                                // itself, in multiples of MinAlignment. See
50                                // comment about its maximum value and in init().
51 };
52
53 typedef atomic_uint64_t AtomicPackedHeader;
54 COMPILER_CHECK(sizeof(UnpackedHeader) == sizeof(PackedHeader));
55
56 // Minimum alignment of 8 bytes for 32-bit, 16 for 64-bit
57 const uptr MinAlignmentLog = FIRST_32_SECOND_64(3, 4);
58 const uptr MaxAlignmentLog = 24;  // 16 MB
59 const uptr MinAlignment = 1 << MinAlignmentLog;
60 const uptr MaxAlignment = 1 << MaxAlignmentLog;
61
62 // constexpr version of __sanitizer::RoundUp without the extraneous CHECK.
63 // This way we can use it in constexpr variables and functions declarations.
64 constexpr uptr RoundUpTo(uptr Size, uptr Boundary) {
65   return (Size + Boundary - 1) & ~(Boundary - 1);
66 }
67
68 namespace Chunk {
69   constexpr uptr getHeaderSize() {
70     return RoundUpTo(sizeof(PackedHeader), MinAlignment);
71   }
72 }
73
74 #if SANITIZER_CAN_USE_ALLOCATOR64
75 const uptr AllocatorSpace = ~0ULL;
76 struct AP64 {
77   static const uptr kSpaceBeg = AllocatorSpace;
78   static const uptr kSpaceSize = AllocatorSize;
79   static const uptr kMetadataSize = 0;
80   typedef __scudo::SizeClassMap SizeClassMap;
81   typedef NoOpMapUnmapCallback MapUnmapCallback;
82   static const uptr kFlags =
83       SizeClassAllocator64FlagMasks::kRandomShuffleChunks;
84   using AddressSpaceView = LocalAddressSpaceView;
85 };
86 typedef SizeClassAllocator64<AP64> PrimaryT;
87 #else
88 static const uptr NumRegions = SANITIZER_MMAP_RANGE_SIZE >> RegionSizeLog;
89 # if SANITIZER_WORDSIZE == 32
90 typedef FlatByteMap<NumRegions> ByteMap;
91 # elif SANITIZER_WORDSIZE == 64
92 typedef TwoLevelByteMap<(NumRegions >> 12), 1 << 12> ByteMap;
93 # endif  // SANITIZER_WORDSIZE
94 struct AP32 {
95   static const uptr kSpaceBeg = 0;
96   static const u64 kSpaceSize = SANITIZER_MMAP_RANGE_SIZE;
97   static const uptr kMetadataSize = 0;
98   typedef __scudo::SizeClassMap SizeClassMap;
99   static const uptr kRegionSizeLog = RegionSizeLog;
100   using AddressSpaceView = LocalAddressSpaceView;
101   using ByteMap = __scudo::ByteMap;
102   typedef NoOpMapUnmapCallback MapUnmapCallback;
103   static const uptr kFlags =
104       SizeClassAllocator32FlagMasks::kRandomShuffleChunks |
105       SizeClassAllocator32FlagMasks::kUseSeparateSizeClassForBatch;
106 };
107 typedef SizeClassAllocator32<AP32> PrimaryT;
108 #endif  // SANITIZER_CAN_USE_ALLOCATOR64
109
110 #include "scudo_allocator_secondary.h"
111 #include "scudo_allocator_combined.h"
112
113 typedef SizeClassAllocatorLocalCache<PrimaryT> AllocatorCacheT;
114 typedef LargeMmapAllocator SecondaryT;
115 typedef CombinedAllocator<PrimaryT, AllocatorCacheT, SecondaryT> BackendT;
116
117 void initScudo();
118
119 void *scudoAllocate(uptr Size, uptr Alignment, AllocType Type);
120 void scudoDeallocate(void *Ptr, uptr Size, uptr Alignment, AllocType Type);
121 void *scudoRealloc(void *Ptr, uptr Size);
122 void *scudoCalloc(uptr NMemB, uptr Size);
123 void *scudoValloc(uptr Size);
124 void *scudoPvalloc(uptr Size);
125 int scudoPosixMemalign(void **MemPtr, uptr Alignment, uptr Size);
126 void *scudoAlignedAlloc(uptr Alignment, uptr Size);
127 uptr scudoMallocUsableSize(void *Ptr);
128
129 }  // namespace __scudo
130
131 #endif  // SCUDO_ALLOCATOR_H_