15f757f3fSDimitry Andric //===-- allocator_common.h --------------------------------------*- C++ -*-===// 25f757f3fSDimitry Andric // 35f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65f757f3fSDimitry Andric // 75f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 85f757f3fSDimitry Andric 95f757f3fSDimitry Andric #ifndef SCUDO_ALLOCATOR_COMMON_H_ 105f757f3fSDimitry Andric #define SCUDO_ALLOCATOR_COMMON_H_ 115f757f3fSDimitry Andric 125f757f3fSDimitry Andric #include "common.h" 135f757f3fSDimitry Andric #include "list.h" 145f757f3fSDimitry Andric 155f757f3fSDimitry Andric namespace scudo { 165f757f3fSDimitry Andric 175f757f3fSDimitry Andric template <class SizeClassAllocator> struct TransferBatch { 185f757f3fSDimitry Andric typedef typename SizeClassAllocator::SizeClassMap SizeClassMap; 195f757f3fSDimitry Andric typedef typename SizeClassAllocator::CompactPtrT CompactPtrT; 205f757f3fSDimitry Andric 215f757f3fSDimitry Andric static const u16 MaxNumCached = SizeClassMap::MaxNumCachedHint; 225f757f3fSDimitry Andric void setFromArray(CompactPtrT *Array, u16 N) { 235f757f3fSDimitry Andric DCHECK_LE(N, MaxNumCached); 245f757f3fSDimitry Andric Count = N; 255f757f3fSDimitry Andric memcpy(Batch, Array, sizeof(Batch[0]) * Count); 265f757f3fSDimitry Andric } 275f757f3fSDimitry Andric void appendFromArray(CompactPtrT *Array, u16 N) { 285f757f3fSDimitry Andric DCHECK_LE(N, MaxNumCached - Count); 295f757f3fSDimitry Andric memcpy(Batch + Count, Array, sizeof(Batch[0]) * N); 305f757f3fSDimitry Andric // u16 will be promoted to int by arithmetic type conversion. 315f757f3fSDimitry Andric Count = static_cast<u16>(Count + N); 325f757f3fSDimitry Andric } 335f757f3fSDimitry Andric void appendFromTransferBatch(TransferBatch *B, u16 N) { 345f757f3fSDimitry Andric DCHECK_LE(N, MaxNumCached - Count); 355f757f3fSDimitry Andric DCHECK_GE(B->Count, N); 365f757f3fSDimitry Andric // Append from the back of `B`. 375f757f3fSDimitry Andric memcpy(Batch + Count, B->Batch + (B->Count - N), sizeof(Batch[0]) * N); 385f757f3fSDimitry Andric // u16 will be promoted to int by arithmetic type conversion. 395f757f3fSDimitry Andric Count = static_cast<u16>(Count + N); 405f757f3fSDimitry Andric B->Count = static_cast<u16>(B->Count - N); 415f757f3fSDimitry Andric } 425f757f3fSDimitry Andric void clear() { Count = 0; } 43*0fca6ea1SDimitry Andric bool empty() { return Count == 0; } 445f757f3fSDimitry Andric void add(CompactPtrT P) { 455f757f3fSDimitry Andric DCHECK_LT(Count, MaxNumCached); 465f757f3fSDimitry Andric Batch[Count++] = P; 475f757f3fSDimitry Andric } 485f757f3fSDimitry Andric void moveToArray(CompactPtrT *Array) { 495f757f3fSDimitry Andric memcpy(Array, Batch, sizeof(Batch[0]) * Count); 505f757f3fSDimitry Andric clear(); 515f757f3fSDimitry Andric } 52*0fca6ea1SDimitry Andric 53*0fca6ea1SDimitry Andric void moveNToArray(CompactPtrT *Array, u16 N) { 54*0fca6ea1SDimitry Andric DCHECK_LE(N, Count); 55*0fca6ea1SDimitry Andric memcpy(Array, Batch + Count - N, sizeof(Batch[0]) * N); 56*0fca6ea1SDimitry Andric Count = static_cast<u16>(Count - N); 57*0fca6ea1SDimitry Andric } 585f757f3fSDimitry Andric u16 getCount() const { return Count; } 595f757f3fSDimitry Andric bool isEmpty() const { return Count == 0U; } 605f757f3fSDimitry Andric CompactPtrT get(u16 I) const { 615f757f3fSDimitry Andric DCHECK_LE(I, Count); 625f757f3fSDimitry Andric return Batch[I]; 635f757f3fSDimitry Andric } 645f757f3fSDimitry Andric TransferBatch *Next; 655f757f3fSDimitry Andric 665f757f3fSDimitry Andric private: 675f757f3fSDimitry Andric CompactPtrT Batch[MaxNumCached]; 685f757f3fSDimitry Andric u16 Count; 695f757f3fSDimitry Andric }; 705f757f3fSDimitry Andric 715f757f3fSDimitry Andric // A BatchGroup is used to collect blocks. Each group has a group id to 725f757f3fSDimitry Andric // identify the group kind of contained blocks. 735f757f3fSDimitry Andric template <class SizeClassAllocator> struct BatchGroup { 745f757f3fSDimitry Andric // `Next` is used by IntrusiveList. 755f757f3fSDimitry Andric BatchGroup *Next; 765f757f3fSDimitry Andric // The compact base address of each group 775f757f3fSDimitry Andric uptr CompactPtrGroupBase; 785f757f3fSDimitry Andric // Cache value of SizeClassAllocatorLocalCache::getMaxCached() 795f757f3fSDimitry Andric u16 MaxCachedPerBatch; 805f757f3fSDimitry Andric // Number of blocks pushed into this group. This is an increment-only 815f757f3fSDimitry Andric // counter. 825f757f3fSDimitry Andric uptr PushedBlocks; 835f757f3fSDimitry Andric // This is used to track how many bytes are not in-use since last time we 845f757f3fSDimitry Andric // tried to release pages. 855f757f3fSDimitry Andric uptr BytesInBGAtLastCheckpoint; 865f757f3fSDimitry Andric // Blocks are managed by TransferBatch in a list. 875f757f3fSDimitry Andric SinglyLinkedList<TransferBatch<SizeClassAllocator>> Batches; 885f757f3fSDimitry Andric }; 895f757f3fSDimitry Andric 905f757f3fSDimitry Andric } // namespace scudo 915f757f3fSDimitry Andric 925f757f3fSDimitry Andric #endif // SCUDO_ALLOCATOR_COMMON_H_ 93