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