124b0c43cSChiaHungDuan //===-- allocator_common.h --------------------------------------*- C++ -*-===// 224b0c43cSChiaHungDuan // 324b0c43cSChiaHungDuan // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 424b0c43cSChiaHungDuan // See https://llvm.org/LICENSE.txt for license information. 524b0c43cSChiaHungDuan // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 624b0c43cSChiaHungDuan // 724b0c43cSChiaHungDuan //===----------------------------------------------------------------------===// 824b0c43cSChiaHungDuan 924b0c43cSChiaHungDuan #ifndef SCUDO_ALLOCATOR_COMMON_H_ 1024b0c43cSChiaHungDuan #define SCUDO_ALLOCATOR_COMMON_H_ 1124b0c43cSChiaHungDuan 1224b0c43cSChiaHungDuan #include "common.h" 1324b0c43cSChiaHungDuan #include "list.h" 1424b0c43cSChiaHungDuan 1524b0c43cSChiaHungDuan namespace scudo { 1624b0c43cSChiaHungDuan 1724b0c43cSChiaHungDuan template <class SizeClassAllocator> struct TransferBatch { 1824b0c43cSChiaHungDuan typedef typename SizeClassAllocator::SizeClassMap SizeClassMap; 1924b0c43cSChiaHungDuan typedef typename SizeClassAllocator::CompactPtrT CompactPtrT; 2024b0c43cSChiaHungDuan 2124b0c43cSChiaHungDuan static const u16 MaxNumCached = SizeClassMap::MaxNumCachedHint; 2224b0c43cSChiaHungDuan void setFromArray(CompactPtrT *Array, u16 N) { 2324b0c43cSChiaHungDuan DCHECK_LE(N, MaxNumCached); 2424b0c43cSChiaHungDuan Count = N; 2524b0c43cSChiaHungDuan memcpy(Batch, Array, sizeof(Batch[0]) * Count); 2624b0c43cSChiaHungDuan } 2724b0c43cSChiaHungDuan void appendFromArray(CompactPtrT *Array, u16 N) { 2824b0c43cSChiaHungDuan DCHECK_LE(N, MaxNumCached - Count); 2924b0c43cSChiaHungDuan memcpy(Batch + Count, Array, sizeof(Batch[0]) * N); 3024b0c43cSChiaHungDuan // u16 will be promoted to int by arithmetic type conversion. 3124b0c43cSChiaHungDuan Count = static_cast<u16>(Count + N); 3224b0c43cSChiaHungDuan } 3324b0c43cSChiaHungDuan void appendFromTransferBatch(TransferBatch *B, u16 N) { 3424b0c43cSChiaHungDuan DCHECK_LE(N, MaxNumCached - Count); 3524b0c43cSChiaHungDuan DCHECK_GE(B->Count, N); 3624b0c43cSChiaHungDuan // Append from the back of `B`. 3724b0c43cSChiaHungDuan memcpy(Batch + Count, B->Batch + (B->Count - N), sizeof(Batch[0]) * N); 3824b0c43cSChiaHungDuan // u16 will be promoted to int by arithmetic type conversion. 3924b0c43cSChiaHungDuan Count = static_cast<u16>(Count + N); 4024b0c43cSChiaHungDuan B->Count = static_cast<u16>(B->Count - N); 4124b0c43cSChiaHungDuan } 4224b0c43cSChiaHungDuan void clear() { Count = 0; } 431a7776abSChiaHungDuan bool empty() { return Count == 0; } 4424b0c43cSChiaHungDuan void add(CompactPtrT P) { 4524b0c43cSChiaHungDuan DCHECK_LT(Count, MaxNumCached); 4624b0c43cSChiaHungDuan Batch[Count++] = P; 4724b0c43cSChiaHungDuan } 4824b0c43cSChiaHungDuan void moveToArray(CompactPtrT *Array) { 4924b0c43cSChiaHungDuan memcpy(Array, Batch, sizeof(Batch[0]) * Count); 5024b0c43cSChiaHungDuan clear(); 5124b0c43cSChiaHungDuan } 521a7776abSChiaHungDuan 531a7776abSChiaHungDuan void moveNToArray(CompactPtrT *Array, u16 N) { 541a7776abSChiaHungDuan DCHECK_LE(N, Count); 551a7776abSChiaHungDuan memcpy(Array, Batch + Count - N, sizeof(Batch[0]) * N); 56f83f7128SChiaHungDuan Count = static_cast<u16>(Count - N); 571a7776abSChiaHungDuan } 5824b0c43cSChiaHungDuan u16 getCount() const { return Count; } 5924b0c43cSChiaHungDuan bool isEmpty() const { return Count == 0U; } 6024b0c43cSChiaHungDuan CompactPtrT get(u16 I) const { 6124b0c43cSChiaHungDuan DCHECK_LE(I, Count); 6224b0c43cSChiaHungDuan return Batch[I]; 6324b0c43cSChiaHungDuan } 6424b0c43cSChiaHungDuan TransferBatch *Next; 6524b0c43cSChiaHungDuan 6624b0c43cSChiaHungDuan private: 6724b0c43cSChiaHungDuan CompactPtrT Batch[MaxNumCached]; 6824b0c43cSChiaHungDuan u16 Count; 6924b0c43cSChiaHungDuan }; 7024b0c43cSChiaHungDuan 7124b0c43cSChiaHungDuan // A BatchGroup is used to collect blocks. Each group has a group id to 7224b0c43cSChiaHungDuan // identify the group kind of contained blocks. 7324b0c43cSChiaHungDuan template <class SizeClassAllocator> struct BatchGroup { 7424b0c43cSChiaHungDuan // `Next` is used by IntrusiveList. 7524b0c43cSChiaHungDuan BatchGroup *Next; 7624b0c43cSChiaHungDuan // The compact base address of each group 7724b0c43cSChiaHungDuan uptr CompactPtrGroupBase; 7824b0c43cSChiaHungDuan // This is used to track how many bytes are not in-use since last time we 7924b0c43cSChiaHungDuan // tried to release pages. 8024b0c43cSChiaHungDuan uptr BytesInBGAtLastCheckpoint; 8124b0c43cSChiaHungDuan // Blocks are managed by TransferBatch in a list. 8224b0c43cSChiaHungDuan SinglyLinkedList<TransferBatch<SizeClassAllocator>> Batches; 83*0347c112SChiaHungDuan // Cache value of SizeClassAllocatorLocalCache::getMaxCached() 84*0347c112SChiaHungDuan u16 MaxCachedPerBatch; 8524b0c43cSChiaHungDuan }; 8624b0c43cSChiaHungDuan 8724b0c43cSChiaHungDuan } // namespace scudo 8824b0c43cSChiaHungDuan 8924b0c43cSChiaHungDuan #endif // SCUDO_ALLOCATOR_COMMON_H_ 90