1 : // Copyright 2014 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 : //
15 : // Declares LargeBlockHeap, a heap that directly grabs pages of memory from the
16 : // OS and redzones blocks with entire pages. This is only intended for use with
17 : // sufficiently large allocations (hence the name) where the redzone overhead
18 : // can be amortized.
19 : //
20 : // SyzyAsan overhead is roughly 45% overall, with 25% coming from memory
21 : // allocation overhead (20 + 16 = 36 bytes of overhead for average allocation
22 : // sizes of 144 bytes in Chrome). If we wish to maintain a similar overhead
23 : // then allocations being fed into the large block heap should be at least
24 : // 32KB in size. Ideally the large allocation heap should not be leaned on too
25 : // heavily as it can cause significant memory fragmentation.
26 :
27 : #ifndef SYZYGY_AGENT_ASAN_HEAPS_LARGE_BLOCK_HEAP_H_
28 : #define SYZYGY_AGENT_ASAN_HEAPS_LARGE_BLOCK_HEAP_H_
29 :
30 : #include <unordered_set>
31 :
32 : #include "syzygy/agent/asan/allocators.h"
33 : #include "syzygy/agent/asan/heap.h"
34 : #include "syzygy/common/recursive_lock.h"
35 :
36 : namespace agent {
37 : namespace asan {
38 :
39 : class MemoryNotifierInterface;
40 :
41 : namespace heaps {
42 :
43 : class LargeBlockHeap : public BlockHeapInterface {
44 : public:
45 : // Constructor.
46 : // @param memory_notifier The memory notifier to use.
47 : // @param internal_heap The heap to use for making internal allocations.
48 : LargeBlockHeap(MemoryNotifierInterface* memory_notifier,
49 : HeapInterface* internal_heap);
50 :
51 : // Virtual destructor.
52 : virtual ~LargeBlockHeap();
53 :
54 : // @name HeapInterface implementation.
55 : // @{
56 : virtual HeapType GetHeapType() const;
57 : virtual uint32 GetHeapFeatures() const;
58 : virtual void* Allocate(size_t bytes);
59 : virtual bool Free(void* alloc);
60 : virtual bool IsAllocated(const void* alloc);
61 : virtual size_t GetAllocationSize(const void* alloc);
62 : virtual void Lock();
63 : virtual void Unlock();
64 : virtual bool TryLock();
65 : // @}
66 :
67 : // @name BlockHeapInterface implementation.
68 : // @{
69 : virtual void* AllocateBlock(size_t size,
70 : size_t min_left_redzone_size,
71 : size_t min_right_redzone_size,
72 : BlockLayout* layout);
73 : virtual bool FreeBlock(const BlockInfo& block_info);
74 : // @}
75 :
76 : // @returns the number of active allocations in this heap.
77 E : size_t size() const { return allocs_.size(); }
78 :
79 : protected:
80 : // Information about an allocation made by this allocator.
81 : struct Allocation {
82 : const void* address;
83 : size_t size;
84 : };
85 :
86 : // Calculates a hash of an Allocation object by forwarding to the STL
87 : // hash for the allocation address.
88 : struct AllocationHash {
89 E : size_t operator()(const Allocation& allocation) const {
90 : std::hash<const void*> hash;
91 E : return hash(allocation.address);
92 E : }
93 : };
94 :
95 : // Functor for determining if 2 allocation objects are identical. This only
96 : // uses the allocation address as a key.
97 : struct AllocationEqualTo {
98 E : bool operator()(const Allocation& a1, const Allocation& a2) const {
99 E : return a1.address == a2.address;
100 E : }
101 : };
102 :
103 : // The collection of allocations that has been made through this allocator.
104 : // It is expected that a small number of allocations will be made, so keeping
105 : // track of these explicitly is fine for now.
106 : typedef std::unordered_set<
107 : Allocation,
108 : AllocationHash,
109 : AllocationEqualTo,
110 : HeapAllocator<Allocation>> AllocationSet;
111 : AllocationSet allocs_; // Under lock_.
112 :
113 : // Free all the allocations owned by this heap.
114 : void FreeAllAllocations();
115 :
116 : // The global lock for this allocator.
117 : ::common::RecursiveLock lock_;
118 :
119 : // The memory notifier in use.
120 : MemoryNotifierInterface* memory_notifier_;
121 :
122 : private:
123 : DISALLOW_COPY_AND_ASSIGN(LargeBlockHeap);
124 : };
125 :
126 : } // namespace heaps
127 : } // namespace asan
128 : } // namespace agent
129 :
130 : #endif // SYZYGY_AGENT_ASAN_HEAPS_LARGE_BLOCK_HEAP_H_
|