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
15namespace scudo {
16
17template <class SizeClassAllocator> struct Batch {
18 typedef typename SizeClassAllocator::SizeClassMap SizeClassMap;
19 typedef typename SizeClassAllocator::CompactPtrT CompactPtrT;
20
21 void setFromArray(CompactPtrT *Array, u16 N) {
22 DCHECK_LE(N, SizeClassAllocator::MaxNumBlocksInBatch);
23 Count = N;
24 memcpy(Blocks, Array, sizeof(Blocks[0]) * Count);
25 }
26 void appendFromArray(CompactPtrT *Array, u16 N) {
27 DCHECK_LE(N, SizeClassAllocator::MaxNumBlocksInBatch - Count);
28 memcpy(Blocks + Count, Array, sizeof(Blocks[0]) * N);
29 // u16 will be promoted to int by arithmetic type conversion.
30 Count = static_cast<u16>(Count + N);
31 }
32 void appendFromBatch(Batch *B, u16 N) {
33 DCHECK_LE(N, SizeClassAllocator::MaxNumBlocksInBatch - Count);
34 DCHECK_GE(B->Count, N);
35 // Append from the back of `B`.
36 memcpy(Blocks + Count, B->Blocks + (B->Count - N), sizeof(Blocks[0]) * N);
37 // u16 will be promoted to int by arithmetic type conversion.
38 Count = static_cast<u16>(Count + N);
39 B->Count = static_cast<u16>(B->Count - N);
40 }
41 void clear() { Count = 0; }
42 bool empty() { return Count == 0; }
43 void add(CompactPtrT P) {
44 DCHECK_LT(Count, SizeClassAllocator::MaxNumBlocksInBatch);
45 Blocks[Count++] = P;
46 }
47 void moveToArray(CompactPtrT *Array) {
48 memcpy(Array, Blocks, sizeof(Blocks[0]) * Count);
49 clear();
50 }
51
52 void moveNToArray(CompactPtrT *Array, u16 N) {
53 DCHECK_LE(N, Count);
54 memcpy(Array, Blocks + Count - N, sizeof(Blocks[0]) * N);
55 Count = static_cast<u16>(Count - N);
56 }
57 u16 getCount() const { return Count; }
58 bool isEmpty() const { return Count == 0U; }
59 CompactPtrT get(u16 I) const {
60 DCHECK_LE(I, Count);
61 return Blocks[I];
62 }
63 Batch *Next;
64
65private:
66 u16 Count;
67 CompactPtrT Blocks[];
68};
69
70// A BatchGroup is used to collect blocks. Each group has a group id to
71// identify the group kind of contained blocks.
72template <class SizeClassAllocator> struct BatchGroup {
73 // `Next` is used by IntrusiveList.
74 BatchGroup *Next;
75 // The compact base address of each group
76 uptr CompactPtrGroupBase;
77 // This is used to track how many bytes are not in-use since last time we
78 // tried to release pages.
79 uptr BytesInBGAtLastCheckpoint;
80 // Blocks are managed by Batch in a list.
81 SinglyLinkedList<Batch<SizeClassAllocator>> Batches;
82 // Cache value of SizeClassAllocatorLocalCache::getMaxCached()
83 // TODO(chiahungduan): Except BatchClass, every Batch stores the same number
84 // of blocks. As long as we make BatchClass follow this constraint, this
85 // field can be removed.
86 u16 MaxCachedPerBatch;
87};
88
89} // namespace scudo
90
91#endif // SCUDO_ALLOCATOR_COMMON_H_
92