xref: /reactos/sdk/lib/rtl/heap.h (revision 7115d7ba)
1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS System Libraries
4  * FILE:            lib/rtl/heap.h
5  * PURPOSE:         Run-Time Libary Heap Manager header
6  * PROGRAMMER:      Aleksey Bragin
7  */
8 
9 /* INCLUDES ******************************************************************/
10 
11 #ifndef RTL_HEAP_H
12 #define RTL_HEAP_H
13 
14 /* Core heap definitions */
15 #define HEAP_FREELISTS 128
16 #define HEAP_SEGMENTS 64
17 
18 #define HEAP_ENTRY_SIZE ((ULONG)sizeof(HEAP_ENTRY))
19 #ifdef _WIN64
20 #define HEAP_ENTRY_SHIFT 4
21 #else
22 #define HEAP_ENTRY_SHIFT 3
23 #endif
24 #define HEAP_MAX_BLOCK_SIZE ((0x80000 - PAGE_SIZE) >> HEAP_ENTRY_SHIFT)
25 
26 #define ARENA_INUSE_FILLER     0xBAADF00D
27 #define ARENA_FREE_FILLER      0xFEEEFEEE
28 #define HEAP_TAIL_FILL         0xab
29 
30 // from ntifs.h, should go to another header!
31 #define HEAP_GLOBAL_TAG                 0x0800
32 #define HEAP_PSEUDO_TAG_FLAG            0x8000
33 #define HEAP_TAG_MASK                  (HEAP_MAXIMUM_TAG << HEAP_TAG_SHIFT)
34 #define HEAP_TAGS_MASK                 (HEAP_TAG_MASK ^ (0xFF << HEAP_TAG_SHIFT))
35 
36 #define HEAP_EXTRA_FLAGS_MASK (HEAP_CAPTURE_STACK_BACKTRACES | \
37                                HEAP_SETTABLE_USER_VALUE | \
38                                HEAP_TAGS_MASK)
39 
40 /* Heap entry flags */
41 #define HEAP_ENTRY_BUSY           0x01
42 #define HEAP_ENTRY_EXTRA_PRESENT  0x02
43 #define HEAP_ENTRY_FILL_PATTERN   0x04
44 #define HEAP_ENTRY_VIRTUAL_ALLOC  0x08
45 #define HEAP_ENTRY_LAST_ENTRY     0x10
46 #define HEAP_ENTRY_SETTABLE_FLAG1 0x20
47 #define HEAP_ENTRY_SETTABLE_FLAG2 0x40
48 #define HEAP_ENTRY_SETTABLE_FLAG3 0x80
49 #define HEAP_ENTRY_SETTABLE_FLAGS (HEAP_ENTRY_SETTABLE_FLAG1 | HEAP_ENTRY_SETTABLE_FLAG2 | HEAP_ENTRY_SETTABLE_FLAG3)
50 
51 /* Signatures */
52 #define HEAP_SIGNATURE         0xeefeeff
53 #define HEAP_SEGMENT_SIGNATURE 0xffeeffee
54 
55 /* Segment flags */
56 #define HEAP_USER_ALLOCATED    0x1
57 
58 /* A handy inline to distinguis normal heap, special "debug heap" and special "page heap" */
59 FORCEINLINE BOOLEAN
60 RtlpHeapIsSpecial(ULONG Flags)
61 {
62     if (Flags & HEAP_SKIP_VALIDATION_CHECKS) return FALSE;
63 
64     if (Flags & (HEAP_FLAG_PAGE_ALLOCS |
65                  HEAP_VALIDATE_ALL_ENABLED |
66                  HEAP_VALIDATE_PARAMETERS_ENABLED |
67                  HEAP_CAPTURE_STACK_BACKTRACES |
68                  HEAP_CREATE_ENABLE_TRACING))
69     {
70         /* This is a special heap */
71         return TRUE;
72     }
73 
74     /* No need for a special treatment */
75     return FALSE;
76 }
77 
78 /* Heap structures */
79 struct _HEAP_COMMON_ENTRY
80 {
81 #ifdef _M_AMD64
82     PVOID PreviousBlockPrivateData;
83 #endif
84     union
85     {
86         struct
87         {
88             USHORT Size;
89             UCHAR Flags;
90             UCHAR SmallTagIndex;
91         };
92         struct
93         {
94 #ifndef _M_AMD64
95             PVOID SubSegmentCode;
96 #else
97             ULONG SubSegmentCodeDummy;
98 #endif
99             USHORT PreviousSize;
100             union
101             {
102                 UCHAR SegmentOffset;
103                 UCHAR LFHFlags;
104             };
105             UCHAR UnusedBytes;
106         };
107         struct
108         {
109             USHORT FunctionIndex;
110             USHORT ContextValue;
111         };
112         struct
113         {
114             ULONG InterceptorValue;
115             USHORT UnusedBytesLength;
116             UCHAR EntryOffset;
117             UCHAR ExtendedBlockSignature;
118         };
119         struct
120         {
121             ULONG Code1;
122             USHORT Code2;
123             UCHAR Code3;
124             UCHAR Code4;
125         };
126         ULONGLONG AgregateCode;
127     };
128 };
129 
130 typedef struct _HEAP_FREE_ENTRY
131 {
132     struct _HEAP_COMMON_ENTRY;
133     LIST_ENTRY FreeList;
134 }  HEAP_FREE_ENTRY, *PHEAP_FREE_ENTRY;
135 
136 typedef struct _HEAP_ENTRY
137 {
138     struct _HEAP_COMMON_ENTRY;
139 }  HEAP_ENTRY, *PHEAP_ENTRY;
140 
141 #ifdef _WIN64
142 C_ASSERT(sizeof(HEAP_ENTRY) == 16);
143 #else
144 C_ASSERT(sizeof(HEAP_ENTRY) == 8);
145 #endif
146 C_ASSERT((1 << HEAP_ENTRY_SHIFT) == sizeof(HEAP_ENTRY));
147 
148 typedef struct _HEAP_TAG_ENTRY
149 {
150     ULONG Allocs;
151     ULONG Frees;
152     ULONG Size;
153     USHORT TagIndex;
154     USHORT CreatorBackTraceIndex;
155     WCHAR TagName[24];
156 } HEAP_TAG_ENTRY, *PHEAP_TAG_ENTRY;
157 
158 typedef struct _HEAP_PSEUDO_TAG_ENTRY
159 {
160     ULONG Allocs;
161     ULONG Frees;
162     SIZE_T Size;
163 } HEAP_PSEUDO_TAG_ENTRY, *PHEAP_PSEUDO_TAG_ENTRY;
164 
165 typedef struct _HEAP_COUNTERS
166 {
167     SIZE_T TotalMemoryReserved;
168     SIZE_T TotalMemoryCommitted;
169     SIZE_T TotalMemoryLargeUCR;
170     SIZE_T TotalSizeInVirtualBlocks;
171     ULONG TotalSegments;
172     ULONG TotalUCRs;
173     ULONG CommittOps;
174     ULONG DeCommitOps;
175     ULONG LockAcquires;
176     ULONG LockCollisions;
177     ULONG CommitRate;
178     ULONG DecommittRate;
179     ULONG CommitFailures;
180     ULONG InBlockCommitFailures;
181     ULONG CompactHeapCalls;
182     ULONG CompactedUCRs;
183     ULONG InBlockDeccommits;
184     SIZE_T InBlockDeccomitSize;
185 } HEAP_COUNTERS, *PHEAP_COUNTERS;
186 
187 typedef struct _HEAP_TUNING_PARAMETERS
188 {
189     ULONG CommittThresholdShift;
190     SIZE_T MaxPreCommittThreshold;
191 } HEAP_TUNING_PARAMETERS, *PHEAP_TUNING_PARAMETERS;
192 
193 typedef struct _HEAP_LIST_LOOKUP
194 {
195     struct _HEAP_LIST_LOOKUP *ExtendedLookup;
196     ULONG ArraySize;
197     ULONG ExtraItem;
198     ULONG ItemCount;
199     ULONG OutOfRangeItems;
200     ULONG BaseIndex;
201     PLIST_ENTRY ListHead;
202     PULONG ListsInUseUlong;
203     PLIST_ENTRY *ListHints;
204 } HEAP_LIST_LOOKUP, *PHEAP_LIST_LOOKUP;
205 
206 #define HEAP_SEGMENT_MEMBERS                \
207     HEAP_ENTRY Entry;                       \
208     ULONG SegmentSignature;                 \
209     ULONG SegmentFlags;                     \
210     LIST_ENTRY SegmentListEntry;            \
211     struct _HEAP *Heap;                     \
212     PVOID BaseAddress;                      \
213     ULONG NumberOfPages;                    \
214     PHEAP_ENTRY FirstEntry;                 \
215     PHEAP_ENTRY LastValidEntry;             \
216     ULONG NumberOfUnCommittedPages;         \
217     ULONG NumberOfUnCommittedRanges;        \
218     USHORT SegmentAllocatorBackTraceIndex;  \
219     USHORT Reserved;                        \
220     LIST_ENTRY UCRSegmentList;              \
221     PVOID LastEntryInSegment //FIXME: non-Vista
222 
223 typedef struct _HEAP
224 {
225     HEAP_SEGMENT_MEMBERS;
226 
227     ULONG Flags;
228     ULONG ForceFlags;
229     ULONG CompatibilityFlags;
230     ULONG EncodeFlagMask;
231     HEAP_ENTRY Encoding;
232     ULONG_PTR PointerKey;
233     ULONG Interceptor;
234     ULONG VirtualMemoryThreshold;
235     ULONG Signature;
236     SIZE_T SegmentReserve;
237     SIZE_T SegmentCommit;
238     SIZE_T DeCommitFreeBlockThreshold;
239     SIZE_T DeCommitTotalFreeThreshold;
240     SIZE_T TotalFreeSize;
241     SIZE_T MaximumAllocationSize;
242     USHORT ProcessHeapsListIndex;
243     USHORT HeaderValidateLength;
244     PVOID HeaderValidateCopy;
245     USHORT NextAvailableTagIndex;
246     USHORT MaximumTagIndex;
247     PHEAP_TAG_ENTRY TagEntries;
248     LIST_ENTRY UCRList;
249     LIST_ENTRY UCRSegments; // FIXME: non-Vista
250     ULONG_PTR AlignRound;
251     ULONG_PTR AlignMask;
252     LIST_ENTRY VirtualAllocdBlocks;
253     LIST_ENTRY SegmentList;
254     struct _HEAP_SEGMENT *Segments[HEAP_SEGMENTS]; //FIXME: non-Vista
255     USHORT AllocatorBackTraceIndex;
256     ULONG NonDedicatedListLength;
257     PVOID BlocksIndex; // HEAP_LIST_LOOKUP
258     PVOID UCRIndex;
259     PHEAP_PSEUDO_TAG_ENTRY PseudoTagEntries;
260     LIST_ENTRY FreeLists[HEAP_FREELISTS]; //FIXME: non-Vista
261     //LIST_ENTRY FreeLists;
262     union
263     {
264         ULONG FreeListsInUseUlong[HEAP_FREELISTS / (sizeof(ULONG) * 8)]; //FIXME: non-Vista
265         UCHAR FreeListsInUseBytes[HEAP_FREELISTS / (sizeof(UCHAR) * 8)]; //FIXME: non-Vista
266     } u;
267     PHEAP_LOCK LockVariable;
268     PRTL_HEAP_COMMIT_ROUTINE CommitRoutine;
269     PVOID FrontEndHeap;
270     USHORT FrontHeapLockCount;
271     UCHAR FrontEndHeapType;
272     HEAP_COUNTERS Counters;
273     HEAP_TUNING_PARAMETERS TuningParameters;
274 } HEAP, *PHEAP;
275 
276 typedef struct _HEAP_SEGMENT
277 {
278     HEAP_SEGMENT_MEMBERS;
279 } HEAP_SEGMENT, *PHEAP_SEGMENT;
280 
281 typedef struct _HEAP_UCR_DESCRIPTOR
282 {
283     LIST_ENTRY ListEntry;
284     LIST_ENTRY SegmentEntry;
285     PVOID Address;
286     SIZE_T Size;
287 } HEAP_UCR_DESCRIPTOR, *PHEAP_UCR_DESCRIPTOR;
288 
289 typedef struct _HEAP_UCR_SEGMENT
290 {
291     LIST_ENTRY ListEntry;
292     SIZE_T ReservedSize;
293     SIZE_T CommittedSize;
294 } HEAP_UCR_SEGMENT, *PHEAP_UCR_SEGMENT;
295 
296 typedef struct _HEAP_ENTRY_EXTRA
297 {
298      union
299      {
300           struct
301           {
302                USHORT AllocatorBackTraceIndex;
303                USHORT TagIndex;
304                ULONG_PTR Settable;
305           };
306           UINT64 ZeroInit;
307      };
308 } HEAP_ENTRY_EXTRA, *PHEAP_ENTRY_EXTRA;
309 
310 typedef HEAP_ENTRY_EXTRA HEAP_FREE_ENTRY_EXTRA, *PHEAP_FREE_ENTRY_EXTRA;
311 
312 typedef struct _HEAP_VIRTUAL_ALLOC_ENTRY
313 {
314     LIST_ENTRY Entry;
315     HEAP_ENTRY_EXTRA ExtraStuff;
316     SIZE_T CommitSize;
317     SIZE_T ReserveSize;
318     HEAP_ENTRY BusyBlock;
319 } HEAP_VIRTUAL_ALLOC_ENTRY, *PHEAP_VIRTUAL_ALLOC_ENTRY;
320 
321 /* Global variables */
322 extern RTL_CRITICAL_SECTION RtlpProcessHeapsListLock;
323 extern BOOLEAN RtlpPageHeapEnabled;
324 
325 /* Functions declarations */
326 
327 /* heap.c */
328 PHEAP_FREE_ENTRY NTAPI
329 RtlpCoalesceFreeBlocks (PHEAP Heap,
330                         PHEAP_FREE_ENTRY FreeEntry,
331                         PSIZE_T FreeSize,
332                         BOOLEAN Remove);
333 
334 PHEAP_ENTRY_EXTRA NTAPI
335 RtlpGetExtraStuffPointer(PHEAP_ENTRY HeapEntry);
336 
337 BOOLEAN NTAPI
338 RtlpValidateHeap(PHEAP Heap, BOOLEAN ForceValidation);
339 
340 BOOLEAN NTAPI
341 RtlpValidateHeapEntry(PHEAP Heap, PHEAP_ENTRY HeapEntry);
342 
343 BOOLEAN NTAPI
344 RtlpValidateHeapHeaders(PHEAP Heap, BOOLEAN Recalculate);
345 
346 /* heapdbg.c */
347 HANDLE NTAPI
348 RtlDebugCreateHeap(ULONG Flags,
349                    PVOID Addr,
350                    SIZE_T TotalSize,
351                    SIZE_T CommitSize,
352                    PVOID Lock,
353                    PRTL_HEAP_PARAMETERS Parameters);
354 
355 BOOLEAN NTAPI
356 RtlDebugDestroyHeap(HANDLE HeapPtr);
357 
358 PVOID NTAPI
359 RtlDebugAllocateHeap(PVOID HeapPtr,
360                      ULONG Flags,
361                      SIZE_T Size);
362 
363 PVOID NTAPI
364 RtlDebugReAllocateHeap(HANDLE HeapPtr,
365                        ULONG Flags,
366                        PVOID Ptr,
367                        SIZE_T Size);
368 
369 BOOLEAN NTAPI
370 RtlDebugFreeHeap(HANDLE HeapPtr,
371                  ULONG Flags,
372                  PVOID Ptr);
373 
374 BOOLEAN NTAPI
375 RtlDebugGetUserInfoHeap(PVOID HeapHandle,
376                         ULONG Flags,
377                         PVOID BaseAddress,
378                         PVOID *UserValue,
379                         PULONG UserFlags);
380 
381 BOOLEAN NTAPI
382 RtlDebugSetUserValueHeap(PVOID HeapHandle,
383                          ULONG Flags,
384                          PVOID BaseAddress,
385                          PVOID UserValue);
386 
387 BOOLEAN
388 NTAPI
389 RtlDebugSetUserFlagsHeap(PVOID HeapHandle,
390                          ULONG Flags,
391                          PVOID BaseAddress,
392                          ULONG UserFlagsReset,
393                          ULONG UserFlagsSet);
394 
395 SIZE_T NTAPI
396 RtlDebugSizeHeap(HANDLE HeapPtr,
397                  ULONG Flags,
398                  PVOID Ptr);
399 
400 /* heappage.c */
401 
402 HANDLE NTAPI
403 RtlpPageHeapCreate(ULONG Flags,
404                    PVOID Addr,
405                    SIZE_T TotalSize,
406                    SIZE_T CommitSize,
407                    PVOID Lock,
408                    PRTL_HEAP_PARAMETERS Parameters);
409 
410 PVOID NTAPI
411 RtlpPageHeapDestroy(HANDLE HeapPtr);
412 
413 PVOID NTAPI
414 RtlpPageHeapAllocate(IN PVOID HeapPtr,
415                      IN ULONG Flags,
416                      IN SIZE_T Size);
417 
418 BOOLEAN NTAPI
419 RtlpPageHeapFree(HANDLE HeapPtr,
420                  ULONG Flags,
421                  PVOID Ptr);
422 
423 PVOID NTAPI
424 RtlpPageHeapReAllocate(HANDLE HeapPtr,
425                        ULONG Flags,
426                        PVOID Ptr,
427                        SIZE_T Size);
428 
429 BOOLEAN NTAPI
430 RtlpPageHeapLock(HANDLE HeapPtr);
431 
432 BOOLEAN NTAPI
433 RtlpPageHeapUnlock(HANDLE HeapPtr);
434 
435 BOOLEAN NTAPI
436 RtlpPageHeapGetUserInfo(PVOID HeapHandle,
437                         ULONG Flags,
438                         PVOID BaseAddress,
439                         PVOID *UserValue,
440                         PULONG UserFlags);
441 
442 BOOLEAN NTAPI
443 RtlpPageHeapSetUserValue(PVOID HeapHandle,
444                          ULONG Flags,
445                          PVOID BaseAddress,
446                          PVOID UserValue);
447 
448 BOOLEAN
449 NTAPI
450 RtlpPageHeapSetUserFlags(PVOID HeapHandle,
451                          ULONG Flags,
452                          PVOID BaseAddress,
453                          ULONG UserFlagsReset,
454                          ULONG UserFlagsSet);
455 
456 BOOLEAN
457 NTAPI
458 RtlpDebugPageHeapValidate(PVOID HeapPtr,
459                           ULONG Flags,
460                           PVOID Block);
461 
462 SIZE_T NTAPI
463 RtlpPageHeapSize(HANDLE HeapPtr,
464                  ULONG Flags,
465                  PVOID Ptr);
466 
467 VOID
468 NTAPI
469 RtlpAddHeapToProcessList(PHEAP Heap);
470 
471 VOID
472 NTAPI
473 RtlpRemoveHeapFromProcessList(PHEAP Heap);
474 
475 VOID
476 NTAPI
477 RtlInitializeHeapManager(VOID);
478 
479 #endif
480