reactos/sdk/lib/rtl/heap.h
Jérôme Gardou 7e5c1872ee [RTL] Improve performance by introducing a hint array for free entries
The array is there for the entries smaller than the decommit threshold, the rationale
being that entries which are larger will likely be split for honoring other allocations
or be coalesced and eventually decommitted.

This with the previous commits make a huge perf boost to memory-intensive applications like cmake

CORE-15793
2021-03-16 13:23:21 +01:00

475 lines
12 KiB
C

/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS System Libraries
* FILE: lib/rtl/heap.h
* PURPOSE: Run-Time Libary Heap Manager header
* PROGRAMMER: Aleksey Bragin
*/
/* INCLUDES ******************************************************************/
#ifndef RTL_HEAP_H
#define RTL_HEAP_H
/* Core heap definitions */
#define HEAP_SEGMENTS 64
#define HEAP_ENTRY_SIZE ((ULONG)sizeof(HEAP_ENTRY))
#ifdef _WIN64
#define HEAP_ENTRY_SHIFT 4
#else
#define HEAP_ENTRY_SHIFT 3
#endif
#define HEAP_MAX_BLOCK_SIZE ((0x80000 - PAGE_SIZE) >> HEAP_ENTRY_SHIFT)
#define ARENA_INUSE_FILLER 0xBAADF00D
#define ARENA_FREE_FILLER 0xFEEEFEEE
#define HEAP_TAIL_FILL 0xab
// from ntifs.h, should go to another header!
#define HEAP_GLOBAL_TAG 0x0800
#define HEAP_PSEUDO_TAG_FLAG 0x8000
#define HEAP_TAG_MASK (HEAP_MAXIMUM_TAG << HEAP_TAG_SHIFT)
#define HEAP_TAGS_MASK (HEAP_TAG_MASK ^ (0xFF << HEAP_TAG_SHIFT))
#define HEAP_EXTRA_FLAGS_MASK (HEAP_CAPTURE_STACK_BACKTRACES | \
HEAP_SETTABLE_USER_VALUE | \
HEAP_TAGS_MASK)
/* Heap entry flags */
#define HEAP_ENTRY_BUSY 0x01
#define HEAP_ENTRY_EXTRA_PRESENT 0x02
#define HEAP_ENTRY_FILL_PATTERN 0x04
#define HEAP_ENTRY_VIRTUAL_ALLOC 0x08
#define HEAP_ENTRY_LAST_ENTRY 0x10
#define HEAP_ENTRY_SETTABLE_FLAG1 0x20
#define HEAP_ENTRY_SETTABLE_FLAG2 0x40
#define HEAP_ENTRY_SETTABLE_FLAG3 0x80
#define HEAP_ENTRY_SETTABLE_FLAGS (HEAP_ENTRY_SETTABLE_FLAG1 | HEAP_ENTRY_SETTABLE_FLAG2 | HEAP_ENTRY_SETTABLE_FLAG3)
/* Signatures */
#define HEAP_SIGNATURE 0xeefeeff
#define HEAP_SEGMENT_SIGNATURE 0xffeeffee
/* Segment flags */
#define HEAP_USER_ALLOCATED 0x1
/* A handy inline to distinguis normal heap, special "debug heap" and special "page heap" */
FORCEINLINE BOOLEAN
RtlpHeapIsSpecial(ULONG Flags)
{
if (Flags & HEAP_SKIP_VALIDATION_CHECKS) return FALSE;
if (Flags & (HEAP_FLAG_PAGE_ALLOCS |
HEAP_VALIDATE_ALL_ENABLED |
HEAP_VALIDATE_PARAMETERS_ENABLED |
HEAP_CAPTURE_STACK_BACKTRACES |
HEAP_CREATE_ENABLE_TRACING))
{
/* This is a special heap */
return TRUE;
}
/* No need for a special treatment */
return FALSE;
}
/* Heap structures */
struct _HEAP_COMMON_ENTRY
{
#ifdef _M_AMD64
PVOID PreviousBlockPrivateData;
#endif
union
{
struct
{
USHORT Size;
UCHAR Flags;
UCHAR SmallTagIndex;
};
struct
{
#ifndef _M_AMD64
PVOID SubSegmentCode;
#else
ULONG SubSegmentCodeDummy;
#endif
USHORT PreviousSize;
union
{
UCHAR SegmentOffset;
UCHAR LFHFlags;
};
UCHAR UnusedBytes;
};
struct
{
USHORT FunctionIndex;
USHORT ContextValue;
};
struct
{
ULONG InterceptorValue;
USHORT UnusedBytesLength;
UCHAR EntryOffset;
UCHAR ExtendedBlockSignature;
};
struct
{
ULONG Code1;
USHORT Code2;
UCHAR Code3;
UCHAR Code4;
};
ULONGLONG AgregateCode;
};
};
typedef struct _HEAP_FREE_ENTRY
{
struct _HEAP_COMMON_ENTRY;
LIST_ENTRY FreeList;
} HEAP_FREE_ENTRY, *PHEAP_FREE_ENTRY;
typedef struct _HEAP_ENTRY
{
struct _HEAP_COMMON_ENTRY;
} HEAP_ENTRY, *PHEAP_ENTRY;
#ifdef _WIN64
C_ASSERT(sizeof(HEAP_ENTRY) == 16);
#else
C_ASSERT(sizeof(HEAP_ENTRY) == 8);
#endif
C_ASSERT((1 << HEAP_ENTRY_SHIFT) == sizeof(HEAP_ENTRY));
C_ASSERT((2 << HEAP_ENTRY_SHIFT) == sizeof(HEAP_FREE_ENTRY));
typedef struct _HEAP_TAG_ENTRY
{
ULONG Allocs;
ULONG Frees;
ULONG Size;
USHORT TagIndex;
USHORT CreatorBackTraceIndex;
WCHAR TagName[24];
} HEAP_TAG_ENTRY, *PHEAP_TAG_ENTRY;
typedef struct _HEAP_PSEUDO_TAG_ENTRY
{
ULONG Allocs;
ULONG Frees;
SIZE_T Size;
} HEAP_PSEUDO_TAG_ENTRY, *PHEAP_PSEUDO_TAG_ENTRY;
typedef struct _HEAP_COUNTERS
{
SIZE_T TotalMemoryReserved;
SIZE_T TotalMemoryCommitted;
SIZE_T TotalMemoryLargeUCR;
SIZE_T TotalSizeInVirtualBlocks;
ULONG TotalSegments;
ULONG TotalUCRs;
ULONG CommittOps;
ULONG DeCommitOps;
ULONG LockAcquires;
ULONG LockCollisions;
ULONG CommitRate;
ULONG DecommittRate;
ULONG CommitFailures;
ULONG InBlockCommitFailures;
ULONG CompactHeapCalls;
ULONG CompactedUCRs;
ULONG InBlockDeccommits;
SIZE_T InBlockDeccomitSize;
} HEAP_COUNTERS, *PHEAP_COUNTERS;
typedef struct _HEAP_TUNING_PARAMETERS
{
ULONG CommittThresholdShift;
SIZE_T MaxPreCommittThreshold;
} HEAP_TUNING_PARAMETERS, *PHEAP_TUNING_PARAMETERS;
typedef struct _HEAP_LIST_LOOKUP
{
struct _HEAP_LIST_LOOKUP *ExtendedLookup;
ULONG ArraySize;
ULONG ExtraItem;
ULONG ItemCount;
ULONG OutOfRangeItems;
ULONG BaseIndex;
PLIST_ENTRY ListHead;
PULONG ListsInUseUlong;
PLIST_ENTRY *ListHints;
} HEAP_LIST_LOOKUP, *PHEAP_LIST_LOOKUP;
#define HEAP_SEGMENT_MEMBERS \
HEAP_ENTRY Entry; \
ULONG SegmentSignature; \
ULONG SegmentFlags; \
LIST_ENTRY SegmentListEntry; \
struct _HEAP *Heap; \
PVOID BaseAddress; \
ULONG NumberOfPages; \
PHEAP_ENTRY FirstEntry; \
PHEAP_ENTRY LastValidEntry; \
ULONG NumberOfUnCommittedPages; \
ULONG NumberOfUnCommittedRanges; \
USHORT SegmentAllocatorBackTraceIndex; \
USHORT Reserved; \
LIST_ENTRY UCRSegmentList
typedef struct _HEAP
{
HEAP_SEGMENT_MEMBERS;
ULONG Flags;
ULONG ForceFlags;
ULONG CompatibilityFlags;
ULONG EncodeFlagMask;
HEAP_ENTRY Encoding;
ULONG_PTR PointerKey;
ULONG Interceptor;
ULONG VirtualMemoryThreshold;
ULONG Signature;
SIZE_T SegmentReserve;
SIZE_T SegmentCommit;
SIZE_T DeCommitFreeBlockThreshold;
SIZE_T DeCommitTotalFreeThreshold;
SIZE_T TotalFreeSize;
SIZE_T MaximumAllocationSize;
USHORT ProcessHeapsListIndex;
USHORT HeaderValidateLength;
PVOID HeaderValidateCopy;
USHORT NextAvailableTagIndex;
USHORT MaximumTagIndex;
PHEAP_TAG_ENTRY TagEntries;
LIST_ENTRY UCRList;
LIST_ENTRY UCRSegments; // FIXME: non-Vista
ULONG_PTR AlignRound;
ULONG_PTR AlignMask;
LIST_ENTRY VirtualAllocdBlocks;
LIST_ENTRY SegmentList;
struct _HEAP_SEGMENT *Segments[HEAP_SEGMENTS]; //FIXME: non-Vista
USHORT AllocatorBackTraceIndex;
ULONG NonDedicatedListLength;
PVOID BlocksIndex; // HEAP_LIST_LOOKUP
PVOID UCRIndex;
PHEAP_PSEUDO_TAG_ENTRY PseudoTagEntries;
LIST_ENTRY FreeLists;
PHEAP_LOCK LockVariable;
PRTL_HEAP_COMMIT_ROUTINE CommitRoutine;
PVOID FrontEndHeap;
USHORT FrontHeapLockCount;
UCHAR FrontEndHeapType;
HEAP_COUNTERS Counters;
HEAP_TUNING_PARAMETERS TuningParameters;
RTL_BITMAP FreeHintBitmap; // FIXME: non-Vista
PLIST_ENTRY FreeHints[ANYSIZE_ARRAY]; // FIXME: non-Vista
} HEAP, *PHEAP;
typedef struct _HEAP_SEGMENT
{
HEAP_SEGMENT_MEMBERS;
} HEAP_SEGMENT, *PHEAP_SEGMENT;
typedef struct _HEAP_UCR_DESCRIPTOR
{
LIST_ENTRY ListEntry;
LIST_ENTRY SegmentEntry;
PVOID Address;
SIZE_T Size;
} HEAP_UCR_DESCRIPTOR, *PHEAP_UCR_DESCRIPTOR;
typedef struct _HEAP_UCR_SEGMENT
{
LIST_ENTRY ListEntry;
SIZE_T ReservedSize;
SIZE_T CommittedSize;
} HEAP_UCR_SEGMENT, *PHEAP_UCR_SEGMENT;
typedef struct _HEAP_ENTRY_EXTRA
{
union
{
struct
{
USHORT AllocatorBackTraceIndex;
USHORT TagIndex;
ULONG_PTR Settable;
};
UINT64 ZeroInit;
};
} HEAP_ENTRY_EXTRA, *PHEAP_ENTRY_EXTRA;
typedef HEAP_ENTRY_EXTRA HEAP_FREE_ENTRY_EXTRA, *PHEAP_FREE_ENTRY_EXTRA;
typedef struct _HEAP_VIRTUAL_ALLOC_ENTRY
{
LIST_ENTRY Entry;
HEAP_ENTRY_EXTRA ExtraStuff;
SIZE_T CommitSize;
SIZE_T ReserveSize;
HEAP_ENTRY BusyBlock;
} HEAP_VIRTUAL_ALLOC_ENTRY, *PHEAP_VIRTUAL_ALLOC_ENTRY;
/* Global variables */
extern RTL_CRITICAL_SECTION RtlpProcessHeapsListLock;
extern BOOLEAN RtlpPageHeapEnabled;
/* Functions declarations */
/* heap.c */
PHEAP_FREE_ENTRY NTAPI
RtlpCoalesceFreeBlocks (PHEAP Heap,
PHEAP_FREE_ENTRY FreeEntry,
PSIZE_T FreeSize,
BOOLEAN Remove);
PHEAP_ENTRY_EXTRA NTAPI
RtlpGetExtraStuffPointer(PHEAP_ENTRY HeapEntry);
BOOLEAN NTAPI
RtlpValidateHeap(PHEAP Heap, BOOLEAN ForceValidation);
BOOLEAN NTAPI
RtlpValidateHeapEntry(PHEAP Heap, PHEAP_ENTRY HeapEntry);
BOOLEAN NTAPI
RtlpValidateHeapHeaders(PHEAP Heap, BOOLEAN Recalculate);
/* heapdbg.c */
HANDLE NTAPI
RtlDebugCreateHeap(ULONG Flags,
PVOID Addr,
SIZE_T TotalSize,
SIZE_T CommitSize,
PVOID Lock,
PRTL_HEAP_PARAMETERS Parameters);
BOOLEAN NTAPI
RtlDebugDestroyHeap(HANDLE HeapPtr);
PVOID NTAPI
RtlDebugAllocateHeap(PVOID HeapPtr,
ULONG Flags,
SIZE_T Size);
PVOID NTAPI
RtlDebugReAllocateHeap(HANDLE HeapPtr,
ULONG Flags,
PVOID Ptr,
SIZE_T Size);
BOOLEAN NTAPI
RtlDebugFreeHeap(HANDLE HeapPtr,
ULONG Flags,
PVOID Ptr);
BOOLEAN NTAPI
RtlDebugGetUserInfoHeap(PVOID HeapHandle,
ULONG Flags,
PVOID BaseAddress,
PVOID *UserValue,
PULONG UserFlags);
BOOLEAN NTAPI
RtlDebugSetUserValueHeap(PVOID HeapHandle,
ULONG Flags,
PVOID BaseAddress,
PVOID UserValue);
BOOLEAN
NTAPI
RtlDebugSetUserFlagsHeap(PVOID HeapHandle,
ULONG Flags,
PVOID BaseAddress,
ULONG UserFlagsReset,
ULONG UserFlagsSet);
SIZE_T NTAPI
RtlDebugSizeHeap(HANDLE HeapPtr,
ULONG Flags,
PVOID Ptr);
/* heappage.c */
HANDLE NTAPI
RtlpPageHeapCreate(ULONG Flags,
PVOID Addr,
SIZE_T TotalSize,
SIZE_T CommitSize,
PVOID Lock,
PRTL_HEAP_PARAMETERS Parameters);
PVOID NTAPI
RtlpPageHeapDestroy(HANDLE HeapPtr);
PVOID NTAPI
RtlpPageHeapAllocate(IN PVOID HeapPtr,
IN ULONG Flags,
IN SIZE_T Size);
BOOLEAN NTAPI
RtlpPageHeapFree(HANDLE HeapPtr,
ULONG Flags,
PVOID Ptr);
PVOID NTAPI
RtlpPageHeapReAllocate(HANDLE HeapPtr,
ULONG Flags,
PVOID Ptr,
SIZE_T Size);
BOOLEAN NTAPI
RtlpPageHeapLock(HANDLE HeapPtr);
BOOLEAN NTAPI
RtlpPageHeapUnlock(HANDLE HeapPtr);
BOOLEAN NTAPI
RtlpPageHeapGetUserInfo(PVOID HeapHandle,
ULONG Flags,
PVOID BaseAddress,
PVOID *UserValue,
PULONG UserFlags);
BOOLEAN NTAPI
RtlpPageHeapSetUserValue(PVOID HeapHandle,
ULONG Flags,
PVOID BaseAddress,
PVOID UserValue);
BOOLEAN
NTAPI
RtlpPageHeapSetUserFlags(PVOID HeapHandle,
ULONG Flags,
PVOID BaseAddress,
ULONG UserFlagsReset,
ULONG UserFlagsSet);
BOOLEAN
NTAPI
RtlpDebugPageHeapValidate(PVOID HeapPtr,
ULONG Flags,
PVOID Block);
SIZE_T NTAPI
RtlpPageHeapSize(HANDLE HeapPtr,
ULONG Flags,
PVOID Ptr);
VOID
NTAPI
RtlpAddHeapToProcessList(PHEAP Heap);
VOID
NTAPI
RtlpRemoveHeapFromProcessList(PHEAP Heap);
VOID
NTAPI
RtlInitializeHeapManager(VOID);
#endif