1 | //===-- allocator_common.h --------------------------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef SCUDO_ALLOCATOR_COMMON_H_ |
10 | #define SCUDO_ALLOCATOR_COMMON_H_ |
11 | |
12 | #include "common.h" |
13 | #include "list.h" |
14 | |
15 | namespace scudo { |
16 | |
17 | template <class SizeClassAllocator> struct TransferBatch { |
18 | typedef typename SizeClassAllocator::SizeClassMap SizeClassMap; |
19 | typedef typename SizeClassAllocator::CompactPtrT CompactPtrT; |
20 | |
21 | static const u16 MaxNumCached = SizeClassMap::MaxNumCachedHint; |
22 | void setFromArray(CompactPtrT *Array, u16 N) { |
23 | DCHECK_LE(N, MaxNumCached); |
24 | Count = N; |
25 | memcpy(Batch, Array, sizeof(Batch[0]) * Count); |
26 | } |
27 | void appendFromArray(CompactPtrT *Array, u16 N) { |
28 | DCHECK_LE(N, MaxNumCached - Count); |
29 | memcpy(Batch + Count, Array, sizeof(Batch[0]) * N); |
30 | // u16 will be promoted to int by arithmetic type conversion. |
31 | Count = static_cast<u16>(Count + N); |
32 | } |
33 | void appendFromTransferBatch(TransferBatch *B, u16 N) { |
34 | DCHECK_LE(N, MaxNumCached - Count); |
35 | DCHECK_GE(B->Count, N); |
36 | // Append from the back of `B`. |
37 | memcpy(Batch + Count, B->Batch + (B->Count - N), sizeof(Batch[0]) * N); |
38 | // u16 will be promoted to int by arithmetic type conversion. |
39 | Count = static_cast<u16>(Count + N); |
40 | B->Count = static_cast<u16>(B->Count - N); |
41 | } |
42 | void clear() { Count = 0; } |
43 | bool empty() { return Count == 0; } |
44 | void add(CompactPtrT P) { |
45 | DCHECK_LT(Count, MaxNumCached); |
46 | Batch[Count++] = P; |
47 | } |
48 | void moveToArray(CompactPtrT *Array) { |
49 | memcpy(Array, Batch, sizeof(Batch[0]) * Count); |
50 | clear(); |
51 | } |
52 | |
53 | void moveNToArray(CompactPtrT *Array, u16 N) { |
54 | DCHECK_LE(N, Count); |
55 | memcpy(Array, Batch + Count - N, sizeof(Batch[0]) * N); |
56 | Count = static_cast<u16>(Count - N); |
57 | } |
58 | u16 getCount() const { return Count; } |
59 | bool isEmpty() const { return Count == 0U; } |
60 | CompactPtrT get(u16 I) const { |
61 | DCHECK_LE(I, Count); |
62 | return Batch[I]; |
63 | } |
64 | TransferBatch *Next; |
65 | |
66 | private: |
67 | CompactPtrT Batch[MaxNumCached]; |
68 | u16 Count; |
69 | }; |
70 | |
71 | // A BatchGroup is used to collect blocks. Each group has a group id to |
72 | // identify the group kind of contained blocks. |
73 | template <class SizeClassAllocator> struct BatchGroup { |
74 | // `Next` is used by IntrusiveList. |
75 | BatchGroup *Next; |
76 | // The compact base address of each group |
77 | uptr CompactPtrGroupBase; |
78 | // Cache value of SizeClassAllocatorLocalCache::getMaxCached() |
79 | u16 MaxCachedPerBatch; |
80 | // Number of blocks pushed into this group. This is an increment-only |
81 | // counter. |
82 | uptr PushedBlocks; |
83 | // This is used to track how many bytes are not in-use since last time we |
84 | // tried to release pages. |
85 | uptr BytesInBGAtLastCheckpoint; |
86 | // Blocks are managed by TransferBatch in a list. |
87 | SinglyLinkedList<TransferBatch<SizeClassAllocator>> Batches; |
88 | }; |
89 | |
90 | } // namespace scudo |
91 | |
92 | #endif // SCUDO_ALLOCATOR_COMMON_H_ |
93 | |