xref: /freebsd/contrib/llvm-project/compiler-rt/lib/scudo/standalone/allocator_common.h (revision 7fdf597e96a02165cfe22ff357b857d5fa15ed8a)
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