//===-- allocator_common.h --------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #ifndef SCUDO_ALLOCATOR_COMMON_H_ #define SCUDO_ALLOCATOR_COMMON_H_ #include "common.h" #include "list.h" namespace scudo { template struct Batch { typedef typename SizeClassAllocator::SizeClassMap SizeClassMap; typedef typename SizeClassAllocator::CompactPtrT CompactPtrT; void setFromArray(CompactPtrT *Array, u16 N) { DCHECK_LE(N, SizeClassAllocator::MaxNumBlocksInBatch); Count = N; memcpy(Blocks, Array, sizeof(Blocks[0]) * Count); } void appendFromArray(CompactPtrT *Array, u16 N) { DCHECK_LE(N, SizeClassAllocator::MaxNumBlocksInBatch - Count); memcpy(Blocks + Count, Array, sizeof(Blocks[0]) * N); // u16 will be promoted to int by arithmetic type conversion. Count = static_cast(Count + N); } void appendFromBatch(Batch *B, u16 N) { DCHECK_LE(N, SizeClassAllocator::MaxNumBlocksInBatch - Count); DCHECK_GE(B->Count, N); // Append from the back of `B`. memcpy(Blocks + Count, B->Blocks + (B->Count - N), sizeof(Blocks[0]) * N); // u16 will be promoted to int by arithmetic type conversion. Count = static_cast(Count + N); B->Count = static_cast(B->Count - N); } void clear() { Count = 0; } bool empty() { return Count == 0; } void add(CompactPtrT P) { DCHECK_LT(Count, SizeClassAllocator::MaxNumBlocksInBatch); Blocks[Count++] = P; } void moveToArray(CompactPtrT *Array) { memcpy(Array, Blocks, sizeof(Blocks[0]) * Count); clear(); } void moveNToArray(CompactPtrT *Array, u16 N) { DCHECK_LE(N, Count); memcpy(Array, Blocks + Count - N, sizeof(Blocks[0]) * N); Count = static_cast(Count - N); } u16 getCount() const { return Count; } bool isEmpty() const { return Count == 0U; } CompactPtrT get(u16 I) const { DCHECK_LE(I, Count); return Blocks[I]; } Batch *Next; private: u16 Count; CompactPtrT Blocks[]; }; // A BatchGroup is used to collect blocks. Each group has a group id to // identify the group kind of contained blocks. template struct BatchGroup { // `Next` is used by IntrusiveList. BatchGroup *Next; // The compact base address of each group uptr CompactPtrGroupBase; // This is used to track how many bytes are not in-use since last time we // tried to release pages. uptr BytesInBGAtLastCheckpoint; // Blocks are managed by Batch in a list. SinglyLinkedList> Batches; // Cache value of SizeClassAllocatorLocalCache::getMaxCached() // TODO(chiahungduan): Except BatchClass, every Batch stores the same number // of blocks. As long as we make BatchClass follow this constraint, this // field can be removed. u16 MaxCachedPerBatch; }; } // namespace scudo #endif // SCUDO_ALLOCATOR_COMMON_H_