xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/scudo/standalone/allocator_common.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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